将参数传递给任务会引发转换类型错误

时间:2019-01-12 08:37:18

标签: c# async-await task

我有2种异步方法可从Dropbox下载文件:

  1. static:从静态文件夹下载静态文件
  2. 动态:根据参数下载文件和文件夹

动态方法失败了,我想了解原因(我考虑使用对象属性来解决)。

private void btnDownload_Click(object sender, EventArgs e)
{
    var task = Task.Run((Func<Task>)Business.DownloadFileFromDropBox);
    task.Wait();

    /* this fails: CS0030 Cannot convert type 'System.Threading.Tasks.Task' to 
       'System.Func<System.Threading.Tasks.Task>' */
    var task2 = Task.Run((Func<Task>)Business.DownloadFromDB("/Files", "File.txt"));
    task2.Wait();
}

我怀疑我的任务和参数方法存在问题。

被调用的方法如下:

    public static async Task DownloadFileFromDropBox()
    {
        string _pathname = "/Files";
        string _filename = "xHistoriekFondsen.csv";
        using (var dbx = new DropboxClient(DropBoxToken))
        {
           using (var response = await dbx.Files.DownloadAsync(_pathname +"/" +  _filename))
            {
                var s = response.GetContentAsByteArrayAsync();
                s.Wait();
                var d = s.Result;
                File.WriteAllBytes(_filename, d);
            }
        }

    }

另一个:

public static async Task DownloadFromDB(string _pathname, string _filename )
    {
        using (var dbx = new DropboxClient(DropBoxToken))
        {
            using (var response = await dbx.Files.DownloadAsync(_pathname + "/" + _filename))
            {
                var s = response.GetContentAsByteArrayAsync();
                s.Wait();
                var d = s.Result;
                File.WriteAllBytes(_filename, d);
            }
        }

    }

1 个答案:

答案 0 :(得分:1)

您在btnDownload_Click中进行的调用本质上是不同的,从而导致出现合理的编译时错误。

  1. 将方法委托传递给Task.Run

在第一种情况(Task.Run((Func<Task>)Business.DownloadFileFromDropBox))中,您已经将DownloadFileFromDropBox方法delegate传递给Task.Run方法,该方法可以按预期工作,因为Task.Run具有一个overload,它以Func<Task>作为参数。

由于方法委托的类型是Func<Task>,它是内置的, 在通用delegate type中,不需要强制转换,您可以将其传递给方法: Task.Run(Business.DownloadFileFromDropBox)

  1. 调用异步方法并将结果传递给Task.Run

在第二种情况(Task.Run((Func<Task>)Business.DownloadFromDB("/Files", "File.txt")))中,您实际上是在调用DownloadFromDB方法并将其结果(Task类型)传递到Task.Run方法中。由于TaskFunc<Task>类型之间的转换不兼容,因此可能会导致编译时错误。

最后,您不需要通过Task方法将Task包装到另一个Task.Run中,只需在Wait对象上直接调用Task从这两种下载方法返回。

var downloadFromDropBoxTask = Business.DownloadFileFromDropBox();
downloadFromDropBoxTask.Wait();

var downloadFromDBTask = Business.DownloadFromDB("/Files", "File.txt");
downloadFromDBTask.Wait()

如果您不会对任务变量执行任何操作(例如错误处理),则可以内联Wait调用:

Business.DownloadFileFromDropBox().Wait();
Business.DownloadFromDB("/Files", "File.txt").Wait();