[英]Changing a synchronous method to async
我已经google了很多并阅读了不同的noob教程,但我不认为我理解正确的做法是什么。 基本上,如果服务器启动并运行,则存在同步的现有代码。 有时,很少,服务器需要更长时间才能启动,所以我想将它包装在一些重试逻辑中。 我构建了一个完全愚蠢的控制台应用程序,试图了解如何异步并等待工作一点点,并提出了这个:
private static int counter = 0;
static void Main(string[] args)
{
DoIt();
Console.ReadLine();
}
static bool LongTask()
{
if (counter == 2)
{
Console.WriteLine("finally true");
Thread.Sleep(1000);
return true;
}
counter++;
Console.WriteLine("false");
Thread.Sleep(1000);
return false;
}
public static Task<bool> WrapperLongTask()
{
Console.WriteLine("wrapper called");
return Task.Run(() => LongTask());
}
public static async Task DoIt()
{
Console.WriteLine("hi");
var result = await WrapperLongTask();
while (result != true)
{
result = await WrapperLongTask();
Console.WriteLine("inside while loop");
}
Console.WriteLine($"outside while loop {result}");
Console.WriteLine("bye");
}
我的LongTask函数表示我当前的函数,它通常在第一次工作时起作用。 是否可以练习然后调用此方法
Task.Run(() => LongTask())
假设这是'ok',那么我基本上会在我的当前方法DoWork()
实际代码中创建它。
Task DoWorkAsync(....) {
return Task.Run(() => DoWork()
}
基本上只是将它包装在Task.Run中,将返回类型更改为Task。 然后,当我稍后调用此方法时,我会做类似的事情
var x = await DoWorkAsync;
// do more stuff with x
这是我应该转换以前的同步方法异步? 提前致谢。
编辑:
DoWork的伪代码(字符串目录,CancellationToken令牌)
var files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
foreach (var file in files) {
try {
token.ThrowIfCancellationRequested();
var fileName = Path.GetFileName(file);
// check if file already exists on server, if not, upload it
}
catch (Exception exception) {
// error handling
}
}
简短的回答是“否”,您不能简单地通过使用Task.Run
包装操作并使方法返回Task
来将所有类型的同步代码转换为异步。
通常,当考虑的操作可能调用某些IO操作(文件系统读/写,网络或Web访问,数据库访问等)时,异步代码是有意义的。
例如,如果您有一个方法使用FileStream.Read
类的同步方法从文件中读取一些数据,然后让某些CPU处理此类文件的内容,那么您可以通过调用FileStream.ReadAsync
将方法转换为异步FileStream.ReadAsync
代替然后异步等待,直到使用await
关键字完成ReadAsync
,然后处理文件的内容(当然你必须更改方法以返回Task
并保持async
)。
在这种情况下的好处是没有线程等待IO操作完成并且线程很昂贵。
没有线程等待IO操作完成的好处在ASP.NET网站等服务器应用程序中非常重要,在这些应用程序中您需要大量的同时请求。 但是,对于简单的应用程序,您可能不希望首先考虑异步代码。
如果要在多个CPU核心上运行多个CPU密集型操作,可以使用Task.Run
。
例如,如果您有4个CPU内核,则通过Task.Run
创建4个任务来处理某些数据是有意义的。 考虑前面的示例,在异步等待ReadAsync
完成后,可以将读取的结果拆分为4个部分(假设数据相对较大),并通过Task.Run
创建4个任务,每个部分将处理一个部分结果。 然后,您可以使用Task.WhenAll
异步等待4个任务完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.