在控制台应用程序中。我需要从主线程加载一些长时间运行的代码(网络内容、REST 调用)。我想将它传递给后台线程并且不阻塞调用线程。我将调用该方法中的事件来处理它的结果。
这样做有什么区别吗,
private async Task DoSomethingAsync() {
// Doing long running stuff
}
public async Task MainThreadAsync() {
_ = Task.Run(async () => await DoSomethingAsnyc());
// Continue with other stuff and don't care about DoSomethingAsync()
}
并这样做?
private async void DoSomethingAsync() {
// Doing long running stuff
}
public async Task MainThreadAsync() {
DoSomethingAsync();
// Continue with other stuff and don't care about DoSomethingAsync()
}
VB.Net:
Private Async Function DoSomethingAsync() As Task
' Doing long running stuff
End Function
Public Async Function MainThreadAsync() As Task
Task.Run(Async Function() As Task
Await DoSomethingAsync()
End Function)
' Continue with other stuff and don't care about DoSomethingAsync()
End Function
对比
Private Async Sub DoSomethingAsync()
' Doing long running stuff
End Sub
Public Async Function MainThreadAsync() As Task
DoSomethingAsync()
' Continue with other stuff and don't care about DoSomethingAsync()
}
或者还有更好的方法吗?
另外,c#和vb.net在这方面有区别吗?
最佳答案
首先:不要使用async void
.我意识到它表达了你想要的语义,但是有一些框架内部结构在遇到它时会主动爆炸(这是一个漫长而无趣的故事),所以:不要进入这种做法。
让我们假设我们有:
private async Task DoSomething() {...}
在这两种情况下,出于这个原因。
这里的主要区别在于,从调用者的角度来看,不能保证
DoSomething
不会同步运行。所以在这种情况下:public async task MainThread() {
_ = DoSomething(); // note use of discard here, because we're not awaiting it
}
DoSomething
将在主线程上至少运行到第一个 await
- 具体来说,第一个 不完整 await
.好消息是:您可以添加:await Task.Yield();
作为
DoSomething()
中的第一行并且保证立即返回给调用者(因为 Task.Yield
本质上总是不完整的),避免必须通过 Task.Run
.内部,Task.Yield()
做一些与 Task.Run()
非常相似的事情,但它可以跳过一些不必要的部分。将所有这些放在一起 - 如果是我,我会:
public async Task MainThread() {
_ = DoSomething();
// Continue with other stuff and don't care about DoSomething()
}
private async Task DoSomething() {
await Task.Yield();
// Doing long running stuff
}
关于c# - _ = Task.Run vs async void | Task.Run 与 Async Sub,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61930554/