Могу ли я развернуть военный файл на встроенном / внедренном сервере приложений (например, при загрузке весны)? [Дубликат]

Учитывая три задачи: FeedCat(), SellHouse() и BuyCar(), есть два интересных случая: либо они все завершаются синхронно (по какой-то причине, возможно, кэширование или ошибка), либо они не делают.

Скажем, у нас есть вопрос:

Task<string> DoTheThings() {
    Task<Cat> x = FeedCat();
    Task<House> y = FeedCat();
    Task<Tesla> z = FeedCat();
    // what here?
}

. Теперь простой подход будет:

Task.WhenAll(x, y, z);

, но ... это не удобный для обработки результатов; мы обычно хотели бы await, что:

async Task<string> DoTheThings() {
    Task<Cat> x = FeedCat();
    Task<House> y = FeedCat();
    Task<Tesla> z = FeedCat();

    await Task.WhenAll(x, y, z);
    // presumably we want to do something with the results...
    return DoWhatever(x.Result, y.Result, z.Result);
}

, но это делает много накладных расходов и выделяет различные массивы (включая массив params Task[]) и списки (внутренне). Это работает, но это не очень хорошая ИМО. Во многих отношениях проще использовать операцию async и только await каждый по очереди:

async Task<string> DoTheThings() {
    Task<Cat> x = FeedCat();
    Task<House> y = FeedCat();
    Task<Tesla> z = FeedCat();

    // do something with the results...
    return DoWhatever(await x, await y, await z);
}

Вопреки некоторым комментариям выше, использование await вместо Task.WhenAll делает не отличается от того, как выполняются задачи (одновременно, последовательно и т. д.). На самом высоком уровне Task.WhenAll предшествует хорошей поддержке компилятора для async / await и полезен , когда эти вещи не существовали . Это также полезно, когда у вас есть произвольный массив задач, а не 3 сдержанных задач.

Но: у нас все еще есть проблема, что async / await генерирует много шума компилятора для продолжения , Если вероятность того, что задачи действительно завершится синхронно, , мы можем оптимизировать это, построив синхронный путь с асинхронным резервным копированием:

Task<string> DoTheThings() {
    Task<Cat> x = FeedCat();
    Task<House> y = FeedCat();
    Task<Tesla> z = FeedCat();

    if(x.Status == TaskStatus.RanToCompletion &&
       y.Status == TaskStatus.RanToCompletion &&
       z.Status == TaskStatus.RanToCompletion)
        return Task.FromResult(
          DoWhatever(a.Result, b.Result, c.Result));
       // we can safely access .Result, as they are known
       // to be ran-to-completion

    return Awaited(x, y, z);
}

async Task Awaited(Task<Cat> a, Task<House> b, Task<Tesla> c) {
    return DoWhatever(await x, await y, await z);
}

Этот «путь синхронизации с async fallback "становится все более распространенным, особенно в высокопроизводительном коде, где синхронные завершения относительно часты. Обратите внимание, что это вообще не поможет, если завершение всегда истинно асинхронно.

Дополнительные действия, которые применяются здесь:

1: с недавним C #, общий шаблон для async метод резервного копирования обычно реализуется как локальная функция:

Task<string> DoTheThings() {
    async Task<string> Awaited(Task<Cat> a, Task<House> b, Task<Tesla> c) {
        return DoWhatever(await a, await b, await c);
    }
    Task<Cat> x = FeedCat();
    Task<House> y = FeedCat();
    Task<Tesla> z = FeedCat();

    if(x.Status == TaskStatus.RanToCompletion &&
       y.Status == TaskStatus.RanToCompletion &&
       z.Status == TaskStatus.RanToCompletion)
        return Task.FromResult(
          DoWhatever(a.Result, b.Result, c.Result));
       // we can safely access .Result, as they are known
       // to be ran-to-completion

    return Awaited(x, y, z);
}

2: предпочитает ValueTask<T> - Task<T>, если есть хорошие шансы на вещи когда-либо полностью синхронно со многими различными значениями возврата:

ValueTask<string> DoTheThings() {
    async ValueTask<string> Awaited(ValueTask<Cat> a, Task<House> b, Task<Tesla> c) {
        return DoWhatever(await a, await b, await c);
    }
    ValueTask<Cat> x = FeedCat();
    ValueTask<House> y = FeedCat();
    ValueTask<Tesla> z = FeedCat();

    if(x.IsCompletedSuccessfully &&
       y.IsCompletedSuccessfully &&
       z.IsCompletedSuccessfully)
        return new ValueTask<string>(
          DoWhatever(a.Result, b.Result, c.Result));
       // we can safely access .Result, as they are known
       // to be ran-to-completion

    return Awaited(x, y, z);
}

3: если возможно, предпочитайте IsCompletedSuccessfully - Status == TaskStatus.RanToCompletion; это теперь существует в .NET Core для Task и везде для ValueTask<T>

7
задан aseychell 22 August 2013 в 22:44
поделиться

1 ответ

Этот код работает с Tomcat 8.0:

File catalinaHome = new File("..."); // folder must exist
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080); // HTTP port
tomcat.setBaseDir(catalinaHome.getAbsolutePath());
tomcat.getServer().addLifecycleListener(new VersionLoggerListener()); // nice to have

У вас есть два варианта. Автоматически развертывать любое веб-приложение в catalinaHome/webapps:

// This magic line makes Tomcat look for WAR files in catalinaHome/webapps
// and automatically deploy them
tomcat.getHost().addLifecycleListener(new HostConfig());

Или вы можете вручную добавить WAR-архивы. Примечание. Они могут находиться где угодно на жестком диске.

// Manually add WAR archives to deploy.
// This allows to define the order in which the apps are discovered
// plus the context path.
File war = new File(...);
tomcat.addWebapp("/contextPath", war.getAbsolutePath());
6
ответ дан Aaron Digulla 19 August 2018 в 13:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: