我一直在阅读异步方法,特别是在C#中使用新的async / await关键字,尽管阅读和阅读了这个论坛,我仍然相信异步需要多线程。请解释一下我的误解!
我知道您可以编写异步方法而不会生成后台线程。超级基本的例子:
data_path = '/Users/abs/Desktop/data'
data_dir_list = os.listdir(data_path)
for dataset in data_dir_list:
if os.path.isdir(os.path.join(data_path, dataset): # <-- if it is a directory
img_list=os.listdir(data_path+'/'+dataset)
print ('Loaded the images of dataset-'+'{}\n'.format(dataset))
但是,当然,这种方法完全没用,无法标记为异步,因为它不是异步。我还得到一个编译器警告,说明缺少&#34; await&#34;运营商,正如所料。好的,那我们可以等待什么呢?我可以等待像Task.Run()这样的东西,但这就失败了,因为我现在正在使用多线程。我在网上找到的任何其他例子都试图证明你不需要多线程,只需这样做:
async System.Threading.Tasks.Task<int> GetZeroAsync()
{
return 0;
}
也许我误解了这一点,但它向我证明的是我&#m> 不是那个启动多线程任务的人,而是我只是打电话给另一个人做的方法。由于CallAnotherAsyncMethod()也是一个异步方法,它必须遵循完全相同的规则,对吗?我不能让每个异步方法永远等待另一个异步子方法,在某些时候它必须停止,除非你想要无限递归。
我目前理解它的方式,我知道这是错误的,是async不使用多线程,但它需要它,否则它只是一个同步方法骗你。
所以这可能会有所帮助。如果异步真的不需要多线程,则必须能够生成以下情况,我无法找到实现它的方法。有人可以创建遵循这些规则的方法示例:
异步。
实际上是异步运行。
不使用任何多线程,如调用Task.Run()或使用BackgroundWorker等。
不会调用任何其他异步方法(除非您也可以证明此方法也遵循这些规则)。
不会像Task.Delay()一样调用Task类的任何方法(除非你也可以证明这个方法也遵循这些规则)。
任何帮助或澄清都会非常有帮助!我觉得自己是个不理解这个话题的白痴。
答案 0 :(得分:2)
不使用任何线程的异步操作的最简单示例是等待事件发生。
使用您选择的框架创建一个UI应用,并有两个按钮,一个名为PrimeButton
,一个名为RunButton
private TaskCompletionSource<object> _event = new TaskCompletionSource<object>();
//You are only allowed to do async void if you are writing a event handler!
public async void PrimeButton_OnClick(object sender, EventArgs e)
{
//I moved the code in to Example() so the async void would not be a distraction.
await Example();
}
public async Task Example()
{
await _event.Task;
MessageBox.Show("Run Clicked");
}
public async void RunButton_OnClick(object sender, EventArgs e)
{
_event.SetResult(null);
}
await将等到您单击第二个按钮,然后才允许代码继续并显示消息框。这里没有额外的线程,所有工作都只使用UI线程完成。
所有Task
是一个对象,代表&#34; 将来某个时候完成的事情&#34;。有些东西可能正在等待后台线程完成,这是由Task.Run
启动的,或者它可能正在等待.SetResult(
上的TaskCompletionSource<T>
调用函数,或者它可以等待某种磁盘或网络IO完成并由OS读入缓冲区(但内部通常通过内置TaskCompletionSource<T>
隐藏在ReadAsync()
函数内部实现,所以它只是重复最后一个例子,周围有一个包装器)