2016-05-31 3 views
-4

У меня есть приложение в Windows Forms с помощью кнопки, которая вызывает следующие действия:C# Задача управления потоком логики не работает должным образом

private async void timeStampDocuments_Click(object sender, System.EventArgs e) 
{ 
    await PerformTask(TimeStampPdfs()); 
} 

Метод PerformTask выглядит следующим образом:

private async System.Threading.Tasks.Task PerformTask(System.Threading.Tasks.Task task) 
{ 
    if(documentsView.CheckedItems.Count > 0) 
    { 
     Enabled = false; 
     try 
     { 
      await task; 
     } 
     catch(System.Exception e) 
     { 
      System.Windows.Forms.MessageBox.Show("Exception: " + e.Message); 
     } 
     progressBar.Value = 0; 
     progressBar.Text = string.Empty; 
     Enabled = true; 
    } 
    else 
    { 
     System.Windows.Forms.MessageBox.Show("Please select at least one document."); 
    } 
} 

Проблема заключается в том что даже если условие ложно (documentsView.CheckedItemsCount равно 0), задача по-прежнему выполняется. Однако, как только задача завершается, появляется MessageBox, говорящий «Пожалуйста, выберите хотя бы один документ».

Если это помогает, метод TimeStampPdfs является:

private System.Threading.Tasks.Task TimeStampPdfs() => System.Threading.Tasks.Task.Run(() => 
    { 
     for (int i = 0; i < documentsView.CheckedItems.Count; i++) 
     { 
      var currentDocument = documentsView.CheckedItems[i].ToString(); 
      if (!string.Equals(
       System.IO.Path.GetExtension(currentDocument), ".pdf", System.StringComparison.InvariantCultureIgnoreCase)) 
      { 
       currentDocument = ConvertToPdf(currentDocument); 
      } 
      TimeStampPdf(currentDocument); 
      Report(new ProgressReport 
      { 
       Total = documentsView.CheckedItems.Count, 
       CurrentCount = i + 1 
      }); 
     } 
    }).ContinueWith(t => 
    { 
     System.Windows.Forms.MessageBox.Show("Files saved with time-stamp on print script in " + OutputRootPath); 
    }, 
     System.Threading.CancellationToken.None, 
     System.Threading.Tasks.TaskContinuationOptions.OnlyOnRanToCompletion, 
     System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext() 
    ); 

Я знаю, что это работает, потому что «Файлы, сохраненные с отметкой времени на печать сценария в ...» отображается окно с сообщением.

+2

Я не вижу, как это даже компилируется, потому что 'TimeStampPdf' определяется как метод ничтожной, и все же вы используете ее * возвращаемое значение (?) * назвать' PerformTask' ?? – sstan

+0

Также вы не передаете 'string' в' TimeStampPdf', когда вы его вызываете. – juharr

+0

@sstan Извините, вы отправили неправильный метод. У меня есть два, которые имеют похожие имена, и совершили неосторожную ошибку в спешке. Правильный метод теперь находится в вопросе. –

ответ

1

Проблема в том, что даже если условие является ложным (documentView.CheckedItemsCount равно 0), задача по-прежнему выполняется.

Это потому, что ваш код запуска TimeStampPdfs задача здесь, перед тем вызова PerformTask:

await PerformTask(TimeStampPdfs()); 

Другими словами, await ли не запустить задачу; скорее, TimeStampPdfs запускает задачу и возвращает задание, которое уже выполняется. await затем (асинхронно) ожидает выполнения задачи . Вы можете найти полезную информацию о моем async intro.

Если я понимаю ваш код правильно, вы, вероятно, хотите передать делегат, который возвращает задачу, например:

private async Task PerformTask(Func<Task> func) 
{ 
    if(documentsView.CheckedItems.Count > 0) 
    { 
    Enabled = false; 
    try 
    { 
     await func(); 
    } 
    ... 
} 


await PerformTask(() => TimeStampPdfs()); 

На стороне записки, я рекомендую использовать await вместо ContinueWith для TimeStampPdfs:

private async Task TimeStampPdfs() 
{ 
    await Task.Run(() => 
    { 
    ... 
    }); 
    MessageBox.Show("Files saved with time-stamp on print script in " + OutputRootPath); 
} 
+0

Спасибо, что исправил его. –

Смежные вопросы