![](/img/trans.png)
[英]ASP.NET Core Web API -How to resolve Warning CS1998 This async method lacks 'await' operators and will run synchronously
[英]Usage of Task.WaitAll without any 'await' operators causing warning CS1998 This async method lacks 'await' operators and will run synchronously
我想我的代码有很多弱点,所以请随时分享任何想法。 顺便说一句,我的主要问题是,当我尝试执行以下操作时,最后,当我想等待所有任务(通过使用 Task.WaitAll)完成以检查是否有任何异常时,它真的会让代码的任何部分同步运行,只是因为缺少“等待”运算符吗?
public class Program
{
static bool mock = true;
static readonly object s_lockSource = new object();
static readonly CancellationTokenSource s_tokenSource = new CancellationTokenSource();
static readonly CancellationToken s_token = s_tokenSource.Token;
public static async Task Main()
{
var sw = new Stopwatch();
sw.Start();
IConfigurationRoot config = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json").Build();
var logger = new LiteLogger(new MemoryStream(), config);
logger.Log(LogLevel.Debug, "Fetching data...");
var jsonHelper = new JsonHelper();
IAsyncIO fileService = mock ? new MockAsyncIO() : new FileService(config, s_token);
IAsyncService webService = mock ? new MockAsyncIO() : new WebService(config, s_token);
var remoteFetchTask = webService.FetchAsync(InOutOptions.None);
var localFetchTask = fileService.FetchAsync(InOutOptions.ForecastPath);
var todaysFetchTask = fileService.FetchAsync(InOutOptions.TodaysPath);
var parseRemoteDataTask = remoteFetchTask
.ContinueWith(task =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Remote fetch task completed!");
logger.Log(LogLevel.Info, "Parsing remote data...");
}
return jsonHelper.FromJsonAsync<Region[]>(task.Result);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var filterRemoteRegionsTask = parseRemoteDataTask
.ContinueWith(task =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Forecasts parsing task completed!");
logger.Log(LogLevel.Info, "Merging data...");
}
Region[] remoteRegions = parseRemoteDataTask.Result.Result;
return Task.Run(() => new DataFilter(config).FilterRegions(remoteRegions));
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var parseLocalDataTask = localFetchTask
.ContinueWith(task =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Local fetch task completed!");
logger.Log(LogLevel.Info, "Parsing local data...");
}
return jsonHelper.FromJsonAsync<Region>(task.Result);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var parseTodaysDataTask = todaysFetchTask
.ContinueWith(task =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Today's fetch task completed!");
logger.Log(LogLevel.Info, "Parsing today's data...");
}
return jsonHelper.FromJsonAsync<Forecast[]>(task.Result);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var mergeTask =
Task.WhenAll(filterRemoteRegionsTask, parseLocalDataTask)
.ContinueWith(_ =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Forecasts parsing task completed!");
logger.Log(LogLevel.Info, "Merging data...");
}
Region localInstance = parseLocalDataTask.Result.Result;
Region remoteInstance = filterRemoteRegionsTask.Result.Result;
var dm = new DataMerger();
return Task.Run(() => dm.MergeRegions(localInstance, remoteInstance));
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var forecastsSerializationTask = mergeTask
.ContinueWith(task =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "MergeTask completed!");
logger.Log(LogLevel.Info, "Serializing forecasts data...");
}
Region newLocalInstance = task.Result.Result;
return jsonHelper.ToJsonAsync(newLocalInstance);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var forecastsStoreTask = forecastsSerializationTask
.ContinueWith(task =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Forecasts serialization task completed!");
logger.Log(LogLevel.Info, "Storing forecasts data...");
}
var newLocalJson = task.Result.Result;
return fileService.PersistAsync(newLocalJson, InOutOptions.ForecastPath);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var todaysDataBuildTask =
Task.WhenAll(parseTodaysDataTask, filterRemoteRegionsTask)
.ContinueWith(_ =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Today's weather parsing task completed!");
logger.Log(LogLevel.Info, "Building today's data...");
}
Region remoteInstance = filterRemoteRegionsTask.Result.Result;
Forecast[] todaysWeathers = parseTodaysDataTask.Result.Result;
var tdb = new TodaysDataBuilder(remoteInstance, todaysWeathers);
return Task.Run(() => tdb.Build());
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var todaysDataSerializationTask = todaysDataBuildTask
.ContinueWith(task =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Today's weather data build task completed!");
logger.Log(LogLevel.Info, "Serializing today's data...");
}
return jsonHelper.ToJsonAsync(task.Result.Result);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var todaysDataStoreTask = todaysDataSerializationTask
.ContinueWith(task =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Today's weather data serialization task completed!");
logger.Log(LogLevel.Info, "Storing today's data...");
}
return fileService.PersistAsync(task.Result.Result, InOutOptions.TodaysPath);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var uiDataBuildTask = Task.WhenAll(mergeTask, todaysDataBuildTask)
.ContinueWith(_ =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Antecedent tasks completed!");
logger.Log(LogLevel.Info, "Building UI data source...");
}
var newLocalInstance = mergeTask.Result.Result;
var newTodaysDatas = todaysDataBuildTask.Result.Result;
var usb = new UiSourceBuilder(newLocalInstance, newTodaysDatas);
return Task.Run(() => usb.Build());
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var uiDataStoreTask = uiDataBuildTask
.ContinueWith(task =>
{
lock (s_lockSource)
{
logger.Log(LogLevel.Success, "Building UI data completed!");
logger.Log(LogLevel.Info, "Saving UI data to source file...");
}
return fileService.PersistAsync(task.Result.Result, InOutOptions.ResultPath);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
try
{
Task.WaitAll(new Task[]
{
localFetchTask,
remoteFetchTask,
todaysFetchTask,
parseLocalDataTask,
parseRemoteDataTask,
parseTodaysDataTask,
mergeTask,
forecastsStoreTask,
todaysDataStoreTask,
uiDataStoreTask
});
sw.Stop();
var overall = sw.Elapsed.TotalSeconds;
logger.Log(LogLevel.Success, "All task completed!");
logger.Log(LogLevel.Info, $"Finished in {overall} second{(overall != 1 ? "s" : "")}");
if (overall <= 1)
logger.Log(LogLevel.Warn, "This application is too fast :)");
}
catch (AggregateException ae)
{
foreach (var e in ae.Flatten().InnerExceptions)
logger.Log(LogLevel.Error,
$"Exception has been thrown at: {e.StackTrace}" +
$"{Environment.NewLine}\t\t{e.Message}");
}
catch (Exception ex)
{
logger.Log(LogLevel.Fatal, ex.ToString());
}
Console.WriteLine("\nPress any key to continue...");
Console.ReadKey();
logger.Dispose();
}
}
完整来源,如果需要更多信息。 也许还值得一提的是,我使用的是 .NET 5.0。
它真的会让代码的任何部分同步运行,只是因为缺少“等待”运算符吗?
是的。 Main
方法将同步运行。 这并不重要,因为它是Main
方法,但是如果您想异步等待任务完成,请使用await Task.WhenAll
而不是Task.WaitAll
。 异步方法还有一个额外的好处,它不会在AggregateException
中包装异常。
在旁注中, 使用await
而不是ContinueWith
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.