Передача параметров в задачу вызывает ошибку типа преобразования - PullRequest
0 голосов
/ 12 января 2019

У меня есть 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 голосов
/ 12 января 2019

Вызовы, которые вы делали в btnDownload_Click, принципиально отличаются, что приводит к разумной ошибке во время компиляции.

  1. Передать делегат метода на Task.Run

В первом случае (Task.Run((Func<Task>)Business.DownloadFileFromDropBox)) вы передали DownloadFileFromDropBox метод делегат методу Task.Run, который работает, как и ожидалось, поскольку Task.Run имеет перегрузку который принимает Func<Task> в качестве параметра.

Так как тип делегата метода Func<Task>, который является в универсальном типе делегата приведение не требуется, вы можете просто передать его в метод: Task.Run(Business.DownloadFileFromDropBox)

  1. Вызвать асинхронный метод и передать результат в Task.Run

Во втором случае (Task.Run((Func<Task>)Business.DownloadFromDB("/Files", "File.txt"))) вы фактически вызываете метод DownloadFromDB и передаете его результат (тип Task) в метод Task.Run. Это, как ожидается, вызывает ошибку во время компиляции из-за несовместимости приведения типов Task и Func<Task>.

В заключение вам не нужно заключать Task в другой Task с помощью Task.Run метода, вы можете просто напрямую вызвать Wait для Task объекта, возвращенного обоими методами загрузки.

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

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

Если вы не будете выполнять какие-либо операции (например, обработку ошибок) с вашей переменной задачи, вы можете встроить Wait call:

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