我正在尝试使用一种新的语法来替换我的旧的"fire-and-forget"调用,希望能够更简单易懂,但似乎一直不成功。以下是一个例子:
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();
}
}
这两种方法实现的功能相同,但是我通过新方法得到了一些东西(不需要结束调用并关闭句柄,尽管这仍然有点值得商榷),但是通过必须等待 Task.Yield()
的新方式失去了它,实际上还需要重新编写所有现有的异步 F&F 方法,只为添加一个单行代码。在性能/清理方面是否有一些看不见的收益?
如果我无法修改后台方法,该如何应用异步?对我来说似乎没有直接的方法,我需要创建一个包装的异步方法来等待 Task.Run()
吗?
编辑:我现在看到自己可能缺少一个真正的问题。问题是:已知一个同步方法 A(),如何使用 async
/await
异步地调用它以“忘记和放手”方式调用,而不会得到比“旧方法”更复杂的解决方案。
Thread.Yield
。我认为这段代码是对async/await哲学的滥用。如果没有异步IO,那么async/await可能不是正确的解决方案。 - spenderasync/await
结合Task.Yield
的做法有一种不好的味道。在这里,使用ThreadPool.QueueUserWorkItem
会更合适。毕竟,这才是你真正想要做的... 将工作发送到线程池,并以相当小的代码占用空间,对吧? - spenderThreadPool.QueueUserWorkItem
vsTask.Factory.StartNew
vsdelegate.BeginInvoke
?如果我要进行更改,我最好以最佳可用方式进行。 - mmix