2014-11-18 3 views
-2

Запуск метода longProcess() в одном из моих C# api и при этом мы хотим дождаться завершения этой задачи. Но в то же время не нужно блокировать пользовательский интерфейс. Я видел много потоков SO, но ничего не помогает в моем случае. Ниже, метод 1 не блокирует пользовательский интерфейс и метод 2, блокирует/замораживает пользовательский интерфейс. Есть предположения?С точки зрения API, дождитесь выполнения задачи, но не блокируйте пользовательский интерфейс

public class MyApiManager 
{ 
    private string _x; 

    public MyApiManager(string x) 
    { 
     _x = x; 
    } 

    public void DoProcess() 
    { 
     // Method 1: Does NOT block UI, but does not wait either 
     Task task = Task.Factory.StartNew(() => 
     { 
      Task longProcess = Task.Factory.StartNew(new Action(longProcess)); 
     }); 
     task.Wait(); 

     // Method 2: BLOCKS UI, also waits 
     //var context = TaskScheduler.FromCurrentSynchronizationContext(); 
     //Task task = Task.Factory.StartNew(() => 
     //{ 

     // var token = Task.Factory.CancellationToken; 
     // Task.Factory.StartNew(() => 
     // { 
     //  longProcess(); 
     // }, token, TaskCreationOptions.None, context); 

     //}); 
     //task.Wait(); 

    } 

    private void longProcess() 
    { 
     // simulate long process 
     Thread.Sleep(10000); 
    } 
} 
+0

Не могу понять проблему. Разве метод 1 не нужен? – Reniuz

+0

Я не уверен, почему я был проголосован :(Это проблема, с которой я столкнулся, я могу дать больше информации. –

+0

@Reniuz, как я уже сказал, нужны обе функции запуска async (метод 1) и в то же время (метод 2). –

ответ

3

Прежде всего, вам нужно отделить свои проблемы.

MyApiManager ничего не должно знать о пользовательских интерфейсах. Он управляет API, и в соответствии с принципом единой ответственности это все он делает.

Read Стивен Toub-х Should I expose synchronous wrappers for asynchronous methods?

Она должна быть ответственность обработчик события UI, чтобы убедиться, что MyApiManager не блокирует пользовательский интерфейс. Таким образом, изменить обработчик события на что-то вроде этого:

public async void ButtonClick_EventHandler(object o, EventArgs args) 
{ 
    //some code 

    await Task.Run(() => apiManager.DoProcess()); 
    //or await Task.Run(apiManager.DoProcess); 

    //some more code 
} 

Оба ваших подходов слишком сложны, вы оберточной задачи в задачах, в задачах ... Просто используйте await Task.Run, это все, что вам нужно.

+0

Несомненно, согласился в отношении принципа единой ответственности. Это не совсем мой код, но попытка дублировать как можно больше, чтобы предоставить достаточно информации. Кроме того, это не поддерживает мой процесс, это тоже то, что я пытаюсь позаботиться. Когда эта кнопка нажата, управление переходит к следующей задаче, которую я хочу сохранить. –

0

В методе 2 TaskScheduler.FromCurrentSynchronizationContext(), скорее всего, вызывается из вашего кода пользовательского интерфейса. , , поэтому вы получаете контекст планировщика пользовательского интерфейса.

Далее вы планируете свою задачу в потоке пользовательского интерфейса, а longProcess() вызывает сон, поэтому вы спите в потоке пользовательского интерфейса. Как и ожидалось, пользовательский интерфейс блокируется.

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

  • Нет связанных вопросов^_^