Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当方法返回void时,是否与任务相同?_C#_Asynchronous_Async Ctp - Fatal编程技术网

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

C# 当方法返回void时,是否与任务相同?,c#,asynchronous,async-ctp,C#,Asynchronous,Async Ctp,我正在尝试async CTP,版本4.5,它允许使用异步方法,而无需编写Begin/End方法 我的第一个探测是执行一个返回void的异步方法。我看到一些示例,并执行以下操作: private void btnAsync01_Click(object sender, RoutedEventArgs e) { UpdateTxtLog("click button: " + System.DateTime.Now); method01Async(); UpdateTxtLog

我正在尝试async 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项目中,我有一个用于查看结果的文本框和一个执行异步方法的按钮

在async方法中,我使用wait,这是必需的,因为该方法是async的,并使用TasEx.Run创建一个新线程,在其中执行代码

我怀疑这一点。在我看到的几个示例中,我看到了如何创建一个返回void的异步方法,请使用Task.Run或TaskEx.Run

如果我没有错,请运行Task.Run创建一个新线程,在其中执行该方法。那么为什么要使用异步方法,如果在任务中创建一个新线程,我得到了我想要的,而不是阻止主线程

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

事实上,我使用相同的代码,没有异步和等待,结果是一样的,主程序没有阻塞,所有的工作都如我所期望的那样。方法如下:

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

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

在这两种情况下,您都没有真正使用async,因为您没有等待原始调用。以下是您应该如何做到这一点:

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

private async Task method01Async()
{
    return await TaskEx.Run(() =>
    {
        UpdateTxtLog("Enter method01Async: " + System.DateTime.Now);
        Thread.Sleep(10000);
        UpdateTxtLog("exit method01Async: " + System.DateTime.Now);
    });
}
一旦您将其更改为此(重要部分是按钮单击事件中的
wait method01Async()
,它将在退出后跳回那里,并且您的“after ethod01Async:”文本日志应该显示10秒延迟,就像
method01Async
方法中的“exit method01Async”日志一样

如果我没有错,请运行Task.Run创建一个新线程,在其中执行该方法

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

那么为什么要使用异步方法,如果在任务中创建一个新线程,我得到了我想要的,而不是阻止主线程

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

因此,如果您使您的
method01Async
成为“可等待的”,也就是说,使其返回一个
任务

private async Task method01Async()
{
    await Task.Run(/* whatever */);
}
然后,您可以通过
btnAsync01\u 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()
实现类似的效果:

我相信你会同意这是更混乱,更不可读

另外,如果异步方法访问一些共享变量,我必须小心并发性,对吗

是的,你说得对

事实上,我使用相同的代码,没有异步和等待,结果是一样的,主程序没有阻塞,所有的工作都如我所期望的那样

结果当然不是我认为您的代码应该做的。单击
btnAsync01\u的最后一行将执行“after method01Async”,但它不会等到在该方法中启动的
任务完成


作为旁注,在
method01Async
中不需要使用
async
。直接返回
任务
(或者不返回,如果您想使其保持
无效
-返回),其工作原理相同:

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

顺便说一句,Visual Studio 11 Beta现在已经推出,它包含了异步CTP的功能,并进行了一些改进和bug修复。在这种情况下,如果在方法中我使用任务,并且任务使用niew线程,那么使用异步方法的操作系统的好处是什么?如果我直接使用任务,而不使用异步方法,那么我会得到该行为。也许如果方法返回值,那么ync方法更有意义,对于void方法,最好直接使用任务?我强烈建议所有
async
方法都返回
task
task
,除非它们是事件处理程序,并且必须返回
void
。这使您能够在必要时组合它们,并且错误处理非常简单也更干净(如果
async void
方法在WPF上下文中引发异常,它将直接发送到UI消息循环,因此
async void
方法不是真正的“触发并忘记”方法)。此外,使用
任务。运行
仅用于在线程池上运行代码。您可以使用
任务。延迟
进行异步等待,而不是将阻塞
睡眠
排队。这将不会编译。如果要在其中使用
等待
,则需要使
btnAsync01\u单击
异步
。是的,需要将单击事件设置为但是用这种方式,我有同样的疑问,如果在method01Async中我使用了一个任务,我使用了一个新线程,所以我看不到使用async的好处。这让我觉得如果异步方法在方法返回结果时更有意义,而对于void方法,可能最好直接使用一个使用任务的线程。@svick是对的。我没有这样做我不能编译它,所以我要从内存开始。编译器会很快告诉你,你不能从一个没有标记为
async
的方法调用
await
。编辑以反映这一点。谢谢svick。@Daimroc,使用
async
/
await
的原因是你希望在它返回时完成一些事情,而不是在它返回之前在这种情况下,
updatextlog(“在ethod01Async:+System.DateTime.Now之后);
将立即运行,如果您不等待
t的返回
private Task method01Async()
{
    return Task.Run(/* whatever */);
}