2016-12-06 2 views
0

Давайте начнем с кодом:C# ждет задание без блокировки пользовательского интерфейса

private void StartStopService() 
{ 
    var task = Task.Run(() => debugService.Iterate()); 
    StartStopInit(true); 

    //task.Wait(); 
    if (task.IsCompleted) 
     StartStopInit(false); 
} 

Я пытаюсь сделать программу, которая будет выполняться список данной DLL файлы из БД по одному, не блокируя поток пользовательского интерфейса в то же время. Предоставляемый метод запускается при нажатии кнопки, и он запускает задачу для перебора DLL.

public void Iterate() 
{ 
    foreach (var plugin in runningPlugins) 
     ExecutePlugin(plugin); 
} 

Выполнение метода просто выполняет DLL по одному.

Мне нужно решение для запуска метода StartStopInit() после завершения работы с DLL. Если я поставлю task.Wait(), я заблокирую UI ... ситуация, поскольку она сейчас, конечно же, не работает, потому что если условие передается при запуске задачи. Если я реализую какой-то бесконечный цикл для прослушивания изменений, я снова заблокирую пользовательский интерфейс. Как я могу решить эту проблему?

+0

Если вы не блокируете пользовательский интерфейс, считаете ли вы, что можете снова запустить операцию, когда она уже выполняется? Я имею в виду, что если 'StartStopService' вызывается на кнопке, считаете ли вы, нужно ли отключать кнопку, пока это происходит? –

+2

Обычный способ теперь в мире async/await - пометить ваш метод как 'async Task' (вместо' void') и использовать 'await task;', чтобы дождаться завершения задачи. Обратите внимание на мой предыдущий комментарий о не блокировании пользовательского интерфейса. –

+0

Ну, идея конца заключается в том, чтобы направить маркер отмены на кнопку, если задача все еще выполняется – Norgul

ответ

4

Если вы можете, вы должны перейти к новым ключевым словам и соседней поддержке async/await.

Для конкретного кода в вашем вопросе, вот что я хотел бы сделать:

  1. Марк метод, как async Task, чтобы понять вызывающий код, что этот метод асинхронной
  2. Использование await на задаче внутри метод, чтобы остановить выполнение и «ожидание» для выполнения этой задачи, прежде чем продолжать

в частности, это то, что это будет выглядеть так:

private async Task StartStopService() 
{ 
    StartStopInit(true); 
    await Task.Run(debugService.Iterate); 
    StartStopInit(false); 
} 

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

Также подумайте над добавлением блоков try/catch, что произойдет, если подзадача выдает исключение?

private async Task StartStopService() 
{ 
    try 
    { 
     StartStopInit(true); 
     await Task.Run(debugService.Iterate); 
    } 
    catch (InvalidOperationException ex) 
    { 
     // What to do here??? 
    } 
    finally 
    { 
     StartStopInit(false); 
    } 
} 
+0

Это отлично работает! Как я могу присвоить ему имя переменной? 'var task = wait ...' не работает? Я хотел бы направить ему токен отмены – Norgul

+0

Чтобы переслать маркер отмены, вы должны отправить его как часть параметров, если задача возвращает что-то, т.е. он определяется как «Задача ', где 'T' - некоторый тип, тогда вы можете использовать' var result = await task' для ожидания задачи и захвата результатов, но если это просто 'Задача', вы можете только дождитесь его завершения. Однако опять же, в качестве параметров должен быть указан токен отмены. –

+0

Я знаю, но для этого мне нужно зарегистрировать задачу как переменную, чтобы узнать, работает она или нет?Я попробовал с var var = new Task (() => ..) ', но если я выполняю' wait task', он не запускается. И 'await task.Start()' throws error ... EDIT ... получил, nvm, спасибо :) – Norgul