Eve*_*ers 10 .net c# async-await .net-4.5
我试图让我的头围绕异步/等待,并认为我确实理解了一些关于使用的事情.但仍然不太清楚在下面的场景中实际的好处是什么.
查看Task.Run用法.第一种方法使用普通委托并使用Thread.Sleep,但第二种方法使用'async'委托和Task.Delay.
我的问题是:这对这种方法有什么影响(或者它没有)?
该方法本身是一种异步方法.代码正在创建一个单独的线程(通过Task.Run),除了执行该委托之外,该线程没有其他任何操作.因此,即使它在Task.Delay上产生等待,在这种情况下有什么用处,因为线程无论如何都是一个孤立的线程没有用于任何其他东西,即使它只是使用Thread.Sleep,线程仍然是上下文切换到处理器的其他线程.
// The task thread uses a async delegate
public async Task<bool> RetrySendEmail(MailMessage message)
{
bool emailSent = false;
await (Task.Run(***async ()*** =>
{
for (int i = 0; i < 3; i++)
{
if (emailSent)
break;
else
// Wait for 5 secs before trying again
***await Task.Delay(5000);***
try
{
Smtphost.Send(message);
emailSent = true;
break;
}
catch (Exception e) { emailSent = false; // log; }
}
return emailSent;
}));
}
// The task thread uses a normal delegate
public async Task<bool> RetrySendEmail(MailMessage message)
{
bool emailSent = false;
await (Task.Run(***()*** =>
{
for (int i = 0; i < 3; i++)
{
if (emailSent)
break;
else
// Wait for 5 secs before trying again
***Thread.Sleep(5000);***
try
{
Smtphost.Send(message);
emailSent = true;
break;
}
catch (Exception e){ emailSent = false; // log; }
}
return emailSent;
}));
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:这对这种方法有什么影响(或者它没有)?
两个不同之处
async在内部使用委托Task.Run意味着您实际运行Task<Task>.这是Task.Run异步识别并为您解开内部任务的事实对您隐藏,这是Task.Factory.StartNew没有做到的事情当您使用异步委托时Task.Run,您创建一个新线程,然后在您点击后产生控制权await Task.Delay.延续将在任意线程池线程上运行.另外,委托由编译器转换为状态机.
使用普通委托,您可以创建一个线程,同步阻止它5秒钟,然后在您离开的位置继续.没有国家机器,没有屈服.
因此,即使它在Task.Delay上产生等待,在这种情况下有什么用处,因为线程无论如何都是一个孤立的线程没有用于任何其他东西,即使它只是使用Thread.Sleep,线程仍然是上下文切换到处理器的其他线程.
使用asyncwith Task.Run可以在您想要同时执行CPU和IO绑定工作时,都在专用线程中.你认为在异步委托产生之后,它会在任意线程上返回.但是,如果您没有使用过Task.Run,并且该async方法是从附加了自定义同步上下文的线程(例如WinformsSynchronizationContext)执行的,那么之后的任何工作await都会返回到UI消息循环,除非您使用了ConfigureAwait(false).
说实话,我没有看到很多场景Task.Run和async使用正确.但有时它确实有意义.
不同之处在于您浪费了一个线程及其分配的时间片。
当您阻塞一个线程5秒钟时,该线程无法在系统的其他部分中用于实际的CPU工作。它还将创建上下文切换,因为该线程无法执行其他任何操作。
当您使用Task.Delay而不是释放该线程时,Thread.Sleep该线程可以返回ThreadPool,执行等待的任务并执行它。
总的来说,当您释放线程时,可以使应用程序更具伸缩性和效率,因为它只需较少的资源即可完成相同的工作或相同数量的资源来进行更多的工作。
当您的操作实际上是异步的时,则无需使用Task.Run(除非您需要后台线程)。您可以只调用该方法并等待返回的任务:
public async Task<bool> RetrySendEmail(MailMessage message)
{
bool emailSent = false;
for (int i = 0; i < 3; i++)
{
if (emailSent)
break;
else
await Task.Delay(5000);
try
{
Smtphost.Send(message);
emailSent = true;
break;
}
catch (Exception e) { emailSent = false; // log; }
}
return emailSent;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3258 次 |
| 最近记录: |