有一些关于异步等待的事情让我神秘化,我想知道是否有人能向我解释一下:
请注意,我的查询是在阅读完之后:http://blogs.msdn.com/b/ericlippert/archive/2010/10/29/asynchronous-programming-in-c-5-0-part-two-whence-await.aspx
所以Eric Lippert说
方法上的“async”修饰符并不意味着“此方法会自动安排在工作线程上异步运行”
为什么我们需要在我们想要异步运行的方法上放置Async?即。
private async Task<int> GetMeInt()
{
return 0;
}
private async void stuff()
{
var num = GetMeInt();
DoStuff();
int end = await num;
for (int i = 0; i < end; i++)
Console.WriteLine("blahblahblah");
}
问题是我们不希望GetMeInt在内部实际执行任何异步操作。我们只是希望它同步运行,但我们希望它在被另一个方法调用时作为一个整体异步运行。将async仅放在Stuff()方法上并允许GetMeInt()在另一个线程上运行并稍后返回似乎更明智。
基本上我相信它会是这样的:
private int GetMeInt()
{
return 0;
}
private async void stuff()
{
int? num = null;
Thread t = new Thread(() => num = GetMeInt());
t.Start();
DoStuff();
t.Join();
for (int i = 0; i < (num??0); i++)
Console.WriteLine("blahblahblah");
}
毕竟,不是只在Stuff()方法上创建的状态机吗?更令人困惑的是,如果我在GetMeInt中放入异步,编译器会发出警告,在任务对象中强制包装GetMeInt()返回的内容并不是很好,这种类型的事情阻止了我们使用其他人异步编写的方法。
为什么他们没有以这样的方式设计它,所以你可以做这样的事情(这是未经测试的理论代码的领域!)。我认为有理由与框架有关,但我认为这种事情会更直观。我错过了关于这种异步业务的明显信息吗?我想我只是忽略警告并继续,我的OCD就不会放过这个。
private async void stuff()
{
var s = Example.Run<int>(Delegate.CreateDelegate(typeof(Delegate), this, "GetMeInt"));
DoStuff();
for (int i = 0; i < s.Result; i++)
Console.WriteLine("blahblahblah");
}
public class Example
{
Thread t;
Object r;
private Example(){}
public static Example<T> Run<T>(Delegate pFunc)
{
Example<T> output = new Example<T>();
output.t = new Thread(() => output.r = (T)pFunc.DynamicInvoke());
output.t.Start();
return output;
}
public sealed class Example<T> : Example
{
public T Result
{
get
{
t.Join();
return (T)r;
}
private set;
}
}
}
我真的不明白,对此事的任何解释都会受到赞赏。
答案 0 :(得分:5)
所有async
修饰符意味着此方法可以await
件事。
由于编译器警告你,除非你真的有await
的东西,否则它完全没用。
你实际上是在询问如何在后台线程上工作,然后异步等待它完成
您可以使用Task.Run()
在后台运行代码,然后await
生成的任务。
答案 1 :(得分:0)
理解异步的关键是严格来说,该方法在其工作完成之前返回。这基本上是关键字表示的唯一内容。您立即返回0的示例不会“卸载”,因此编译器会警告您没有任何异步。
这就是为什么异步方法应该返回Task<T>
(这样你就可以确定方法的工作何时实际完成并对现有结果采取行动),这就是为什么任何使用await的东西本身都是异步的(因为现在外部方法也在“完成”之前返回)。