首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否需要从异步任务返回任何内容?

是否需要从异步任务返回任何内容?
EN

Stack Overflow用户
提问于 2020-02-21 15:59:01
回答 3查看 182关注 0票数 0

我有以下代码:

代码语言:javascript
复制
    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>并返回真正的修复,但这是必要的吗?

此外,在以下几个方面之间是否有什么区别:

代码语言:javascript
复制
_ = PopulateMetrics()

代码语言:javascript
复制
await PopulateMetrics()

下面是调用方法的内容。注意,除了PopulateMetrics之外,我在每个异步方法中都有异常处理。

代码语言:javascript
复制
        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();
        }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-02-21 16:00:27

通常,当非异步方法返回void时,异步方法应返回Task

代码语言:javascript
复制
public static async Task PopulateMetrics()

据微软称,只有在实现事件处理程序时才应使用从异步方法返回的void

空-返回异步方法有一个特定的目的:使异步事件处理程序成为可能。有可能有一个返回某些实际类型的事件处理程序,但这在语言中不能很好地工作;调用返回类型的事件处理程序是非常尴尬的,而事件处理程序实际上返回某些内容的概念没有多大意义。事件处理程序自然返回void,因此异步方法返回void,这样您就可以拥有一个异步事件处理程序。

票数 5
EN

Stack Overflow用户

发布于 2020-02-21 16:04:55

1)通常,您希望返回一个任务。主要的例外应该是当您需要一个空返回类型时(对于事件)。如果没有理由不让来电者等待你的任务,那为什么不允许呢?

2)返回void的异步方法在另一个方面是特殊的:它们表示顶级异步操作,并且在任务返回异常时具有其他规则。最简单的方法是用一个例子来显示两者之间的区别:

代码语言:javascript
复制
    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处理程序将运行。你不应该让这种事发生。用你的例子,

代码语言:javascript
复制
    public static async void AsyncMethod2(int num)
    {
        await Task.Factory.StartNew(() => Thread.Sleep(num));
    }

是的,使用异步并在此等待,如果抛出异常,它们将确保您的方法仍然正确工作。

有关更多信息,请参见:http://msdn.microsoft.com/en-us/magazine/jj991977.aspx

票数 1
EN

Stack Overflow用户

发布于 2020-02-21 16:15:40

只需将返回类型设置为Task,以消除IDE警告:

代码语言:javascript
复制
 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;
            }
        });
    }

关于这两个调用之间的差异,您必须认为调用异步方法就像启动一个新线程:在等待任务或请求任务结果之前不会阻塞当前线程。请考虑以下代码:

代码语言:javascript
复制
class Program
{
   static async Task Main() // Compiler will warn you 'cause you're not awaiting!
   {
        _ = PopulateMetrics();

       // do something else
   }
}

程序有可能在任务完成之前退出。因为PopulateMetrics返回异步任务,所以您应该这样做:

代码语言:javascript
复制
class Program
{
   static async Task Main() 
   {
       var popMetricsTask = PopulateMetrics();

       // do something else

       popMetricsTask.Wait(); // or: await popMetricsTask;
   }
}

确定您的任务在退出程序之前已经完成。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60342278

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档