使用异步vs“旧异步委托”进行即发即弃

使用异步vs“旧异步委托”进行即发即弃

我试图用一种新语法替换我的旧的“即发即弃”调用,希望更简单,它似乎在逃避我。这是一个例子

class Program{
    static void DoIt(string entry) 
    { 
        Console.WriteLine("Message: " + entry);
    }

    static async void DoIt2(string entry)
    {
        await Task.Yield();
        Console.WriteLine("Message2: " + entry);
    }

    static void Main(string[] args)
    {
        // old way
        Action<string> async = DoIt;
        async.BeginInvoke("Test", ar => { async.EndInvoke(ar); ar.AsyncWaitHandle.Close(); }, null);
        Console.WriteLine("old-way main thread invoker finished");
        // new way
        DoIt2("Test2");   
        Console.WriteLine("new-way main thread invoker finished");
        Console.ReadLine();
    }}

两种方法都做同样的事情,但是我似乎已经获得了(没有必要EndInvoke和关闭处理,这仍然有点争议)我正在以新的方式失去等待a Task.Yield(),这实际上带来了一个新的问题必须重写所有现有的异步F&F方法只是为了添加一个单行。在性能/清理方面是否有一些无形的收获?

如果我无法修改背景方法,我将如何应用异步?在我看来,没有直接的方法,我将不得不创建一个等待Task.Run()的包装器异步方法?

编辑:我现在看到我可能会错过一个真正的问题。问题是:给定一个同步方法A(),如何使用asyncawait以一种即发即忘的方式异步调用它,而不会得到比“旧方式”更复杂的解决方案


侃侃无极
浏览 392回答 3
3回答

肥皂起泡泡

正如其他答案中所述,并且通过这篇优秀的博客文章,您希望避免async void在UI事件处理程序之外使用。如果你想要一个安全的&nbsp;“即发即忘”&nbsp;async方法,请考虑使用这种模式(信用卡@ReedCopsey;这种方法是他在聊天对话中给我的方法):为Task。创建扩展方法。它运行传递Task和捕获/记录任何异常:static&nbsp;async&nbsp;void&nbsp;FireAndForget(this&nbsp;Task&nbsp;task){ &nbsp;&nbsp;&nbsp;try &nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;await&nbsp;task; &nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;e) &nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;log&nbsp;errors &nbsp;&nbsp;&nbsp;}}永远不要在创建时使用Task样式async方法async void。以这种方式调用这些方法:MyTaskAsyncMethod().FireAndForget();你不需要await它(也不会产生await警告)。它也会正确处理任何错误,因为这是你放置的唯一地方async void,你不必记得在try/catch任何地方放置块。如果你真的想要它,你还可以选择不使用该async方法作为“即发即弃”的方法await。

墨色风雨

对我来说,似乎“等待”某些东西和“发射并忘记”是两个正交的概念。您可以异步启动方法而不关心结果,或者您希望在操作完成后继续在原始上下文上执行(并且可能使用返回值),这正是await所做的。如果你只想在ThreadPool线程上执行一个方法(这样你的UI不会被阻止),那就去吧Task.Factory.StartNew(()&nbsp;=>&nbsp;DoIt2("Test2"))你会没事的
打开App,查看更多内容
随时随地看视频慕课网APP