我从main调用了2个相同的任务(比如这个
)static void Main()
{
Downloads test = new Downloads();
test.DisplayResultAsync();
test.DisplayResultAsync();
Console.WriteLine("main");
Console.ReadLine();
}
),其中DisplayResultAsync
是
public async Task DisplayResultAsync()
{
byte[] result = await DownLoadFile();
Console.WriteLine("Downloading complete", result[0]);
}
static Task<byte[]> DownLoadFile()
{
FileDownLoader flDl = new FileDownLoader();
return Task.Run(() =>
{
byte[] result = flDl.Download("test");
return result;
});
}
我想在后台执行此任务,但第二项任务应该在第一项任务完成时开始。
FileDownLoader代码:
class FileDownLoader
{
public byte[] Download(string url)
{
Thread.Sleep(2000);
return new byte[] { 1, 2, 3, 4 };
}
}
我该怎么用?因为这个任务一起执行
答案 0 :(得分:1)
这里有几个问题。首先,您需要使用asynchronous file I/O来执行实际的文件下载,这样您就不会阻止线程。看来你的FileDownLoader
课程现在只是伪造它,这很好但是至少假装它是异步的:
class FileDownLoader
{
public async byte[] DownloadAsync(string url)
{
await Task.Delay(2000);
return new byte[] { 1, 2, 3, 4 };
}
}
允许您执行的操作是删除调用代码中的Task.Run
。 (对于这样的I / O绑定工作,异步就是消耗更少的线程,而不是更多。无论何时在异步方法中看到Task.Run
,它通常 你做过的一个标志有些不对劲。)
继续,您可以将DisplayResultAsync
和DownLoadFile
合并到此:
public async Task DownloadAndDisplayResultAsync()
{
FileDownLoader flDl = new FileDownLoader();
byte[] result = await flDl.DownloadAsync("test");
Console.WriteLine("Downloading complete", result[0]);
}
您想要调用上述方法两次,但是您不希望第二次调用在第一次完成之前启动。 await
允许您轻松无阻塞地执行此操作,但您只能使用async
方法(而不是Main
)执行此操作,因此我们在您的控制台应用中引入一种新方法:
static async Task DoWorkAsync()
{
Downloads test = new Downloads();
await test.DisplayResultAsync();
await test.DisplayResultAsync();
}
现在我们只需要从Main
调用它。你说你希望下载“在后台”发生,所以你可能想要同时进行一些“前景”工作。这是评论的地方:
static void Main()
{
var task = DoWorkAsync();
// do "foreground" work here
task.Wait();
Console.ReadLine();
}
作为附注,使用异步代码的另一个经验法则是,永远不应阻止.Wait()
或.Result
,除{/ 1>之外的的异步调用控制台应用程序的方法。在所有其他情况下使用Main
。