gpt4 book ai didi

c# - 当方法返回 void 时,是否与任务相同?

转载 作者:太空狗 更新时间:2023-10-29 19:41:30 24 4
gpt4 key购买 nike

我正在尝试异步 CTP,版本 4.5 允许使用异步方法而无需编写 Begin/End 方法。

我的第一个尝试是执行一个返回 void 的异步方法。我看到了几个示例并执行了以下操作:

private void btnAsync01_Click(object sender, RoutedEventArgs e)
{
UpdateTxtLog("click button: " + System.DateTime.Now);
method01Async();
UpdateTxtLog("after ethod01Async: " + System.DateTime.Now);
}

private async void method01Async()
{
await TaskEx.Run(() =>
{
UpdateTxtLog("Enter method01Async: " + System.DateTime.Now);
Thread.Sleep(10000);
UpdateTxtLog("exit method01Async: " + System.DateTime.Now);
});
}

在我的 WPF 项目中,我有一个用于查看结果的文本框和一个执行异步方法的按钮。

在异步方法中,我使用 await,这是需要的,因为该方法是异步的,并且使用 TasEx.Run 创建一个新线程来执行代码。

我的疑惑就在这一点上。在我看到的几个例子中,我看到了如何创建一个返回 void 的异步方法,使用这种方式,Task.Run 或 TaskEx.Run。

如果我没记错的话,Task.Run 会创建一个新线程来执行该方法。那为什么要用async方法,如果有了Task,创建一个新线程,我得到我想要的,而不是阻塞主线程?

此外,如果异步方法访问某些共享变量,我必须小心并发,对吗?所以我不知道使用异步方法的优势,至少在这种情况下是这样。

事实上,我在没有异步和等待的情况下使用相同的代码,结果是一样的,主程序没有阻塞,一切都按我预期的那样工作。方法是这样的:

private void method01Async()
{
TaskEx.Run(() =>
{
UpdateTxtLog("Enter method01Async: " + System.DateTime.Now);
Thread.Sleep(10000);
UpdateTxtLog("Exit method01Async: " + System.DateTime.Now);
});
}

我的问题是,当方法返回 void 时,这是使用异步的正确方法吗?

最佳答案

If I am not wrong, Task.Run create a new thread where to execute the method.

不完全是。 Task.Run() 将在不同于 UI 线程的线程上运行代码(至少使用默认的 TaskScheduler)。但在大多数情况下,它实际上不会创建一个新线程,它会重用ThreadPool 中的现有线程。

Then why to use an async method, if with the Task, creating a new thread, I get what I want, not to block the main thread?

在 UI 应用程序的上下文中,async 的要点是能够在异步操作完成后轻松地在 UI 线程上执行一些代码。

因此,如果您将 method01Async 设为“可等待”,也就是说,让它返回一个 Task:

private async Task method01Async()
{
await Task.Run(/* whatever */);
}

然后您可以从 btnAsync01_Click 方法中等待它,如果您将其设置为“异步”:

private async void btnAsync01_Click(object sender, RoutedEventArgs e)
{
UpdateTxtLog("click button: " + System.DateTime.Now);
await method01Async();
UpdateTxtLog("after method01Async: " + System.DateTime.Now);
}

这样,方法的最后一行只有在method01Async中的Task执行完毕后才会执行。它将在 UI 线程上执行。

在 .Net 4.0 中,您可以使用 ContinueWith()Dispatcher.Invoke() 实现类似的效果:

private void btnAsync01_Click(object sender, RoutedEventArgs e)
{
UpdateTxtLog("click button: " + System.DateTime.Now);
method01Async().ContinueWith(() =>
Dispatcher.Invoke(
new Action(() =>
UpdateTxtLog("after method01Async: " + System.DateTime.Now)));
}

我相信您会同意这更加困惑且可读性差。

Also, if the async method access some shared variable, I must be careful with the concurrency, right?

是的,你是对的。

In fact, I use the same code without async and without await and the result is the same, the main program is not blocking and all works as I expect.

结果肯定不是我认为您的代码应该做的。 btnAsync01_Click 的最后一行将执行“after method01Async”,但它不会等到该方法中启动的 Task 完成。


附带说明,无需在 method01Async 中使用 async。直接返回 Task(或者不返回,如果你想让它保持 void-returning),效果是一样的:

private Task method01Async()
{
return Task.Run(/* whatever */);
}

关于c# - 当方法返回 void 时,是否与任务相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10042912/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com