我有以下代码:
public static async void PopulateMetrics()
{
await Task.Run(() =>
{
if (App.CPUSpeed == 0)
{
var stopWatch = Stopwatch.StartNew();
stopWatch.Start();
ArrayList al = new ArrayList(); for (int i = 0; i < 5000000; i++) al.Add("hello");
App.CPUSpeed = 20000 / stopWatch.ElapsedMilliseconds;
}
});
}IDE告诉我异步方法不应该返回void。会让它返回Task<bool>并返回真正的修复,但这是必要的吗?
此外,在以下几个方面之间是否有什么区别:
_ = PopulateMetrics()和
await PopulateMetrics()下面是调用方法的内容。注意,除了PopulateMetrics之外,我在每个异步方法中都有异常处理。
if (Connectivity.NetworkAccess == NetworkAccess.Internet)
{
if (Settings.Rev == REV.No && (new[] { 15, 30, 50 }).Contains(Settings.Trk2))
{
_ = ReviewAppAsync(Settings.Trk2);
}
if (App.devIsPhysical && (new[] { 10, 20, 30 }).Contains(Settings.Trk2))
{
_ = CheckLatestVersion();
}
_ = Helper.PopulateMetrics();
_ = Helper.LogStart();
}发布于 2020-02-21 16:00:27
通常,当非异步方法返回void时,异步方法应返回Task。
public static async Task PopulateMetrics()据微软称,只有在实现事件处理程序时才应使用从异步方法返回的void:
空-返回异步方法有一个特定的目的:使异步事件处理程序成为可能。有可能有一个返回某些实际类型的事件处理程序,但这在语言中不能很好地工作;调用返回类型的事件处理程序是非常尴尬的,而事件处理程序实际上返回某些内容的概念没有多大意义。事件处理程序自然返回void,因此异步方法返回void,这样您就可以拥有一个异步事件处理程序。
发布于 2020-02-21 16:04:55
1)通常,您希望返回一个任务。主要的例外应该是当您需要一个空返回类型时(对于事件)。如果没有理由不让来电者等待你的任务,那为什么不允许呢?
2)返回void的异步方法在另一个方面是特殊的:它们表示顶级异步操作,并且在任务返回异常时具有其他规则。最简单的方法是用一个例子来显示两者之间的区别:
static async void f()
{
await h();
}
static async Task g()
{
await h();
}
static async Task h()
{
throw new NotImplementedException();
}
private void button1_Click(object sender, EventArgs e)
{
f();
}
private void button2_Click(object sender, EventArgs e)
{
g();
}
private void button3_Click(object sender, EventArgs e)
{
GC.Collect();
}F的例外总是被“观察”。离开顶级异步方法的异常被简单地处理为任何其他未处理的异常。G的例外从未被观察到。当垃圾收集器来清理任务时,它会看到任务导致异常,没有人处理异常。当发生这种情况时,TaskScheduler.UnobservedTaskException处理程序将运行。你不应该让这种事发生。用你的例子,
public static async void AsyncMethod2(int num)
{
await Task.Factory.StartNew(() => Thread.Sleep(num));
}是的,使用异步并在此等待,如果抛出异常,它们将确保您的方法仍然正确工作。
有关更多信息,请参见:http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
发布于 2020-02-21 16:15:40
只需将返回类型设置为Task,以消除IDE警告:
public static async Task PopulateMetrics()
{
await Task.Run(() =>
{
if (App.CPUSpeed == 0)
{
var stopWatch = Stopwatch.StartNew();
stopWatch.Start();
ArrayList al = new ArrayList(); for (int i = 0; i < 5000000; i++) al.Add("hello");
App.CPUSpeed = 20000 / stopWatch.ElapsedMilliseconds;
}
});
}关于这两个调用之间的差异,您必须认为调用异步方法就像启动一个新线程:在等待任务或请求任务结果之前不会阻塞当前线程。请考虑以下代码:
class Program
{
static async Task Main() // Compiler will warn you 'cause you're not awaiting!
{
_ = PopulateMetrics();
// do something else
}
}程序有可能在任务完成之前退出。因为PopulateMetrics返回异步任务,所以您应该这样做:
class Program
{
static async Task Main()
{
var popMetricsTask = PopulateMetrics();
// do something else
popMetricsTask.Wait(); // or: await popMetricsTask;
}
}确定您的任务在退出程序之前已经完成。
https://stackoverflow.com/questions/60342278
复制相似问题