2014-01-20 6 views
2

У меня есть два метода, используя в главном методе, как этотКак использовать многопоточность или шаблон задач в следующем сценарии

public bool isBadMethod() 
{ 
    bool isBad = Method1(); 
    if(isBad) return true; 
    else return Method2(); 
} 

bool Method1() { ..... return true or false }   
bool Method2() { ..... return true or false } 

Если какой-либо из Method1 или Method2 не возвращает истину не нужно проверять для другого метода мы можем вернуться MainMethod, как правда. Но если первый метод возвращает false, тогда нужно проверить второй метод и, наконец, вернуть любой второй метод. Здесь Method1 и Method2 являются трудоемкими методами. Могу ли я использовать асинхронное программирование для этих методов. Помогите, как это сделать. (Я использую .net 4.0)

+0

В теории вы могли бы начать оба в отдельных задачах. Затем, если Method1() возвращает true, отмените Method2(); иначе дождитесь завершения метода Method2(). Это зависит от того, что вы можете отменить Method2() –

ответ

4

Вы можете просто использовать короткое замыкание выражений:

bool val = Method1() || Method2(); 

Если Method1 возвращает true, это не напрягает со вторым методом.

Очевидно, что если вызовы метода дороги, то продолжайте работу с маршрутом задачи, поскольку это не параллельное выполнение. Я просто отправляю это на случай, если это проблема XY.


Использование задач, это может быть что-то вроде того, что вы хотите. Он будет запускать оба метода, а затем просто использовать выражение, чтобы получить правильный результат. В этом случае он ждет полных 3 секунд, чтобы захватить результат Method2. Это также отменяет. Я не уверен, если типы используются лучшие практики, как мой опыт с этим неоднородно, но он получает работу в моей песочнице:

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     var cm2 = new CancellationTokenSource(); 

     var m1 = Task.Factory.StartNew(() => Method1()); 
     var m2 = Task.Factory.StartNew(() => Method2(cm2.Token), cm2.Token); 

     var val = m1.Result || m2.Result; 

     cm2.Cancel(); 

     Console.WriteLine(val); 
     Console.ReadLine(); 
    } 

    private static bool Method1() 
    { 
     Thread.Sleep(1000); 
     Console.WriteLine(1); 
     return true; 
    } 

    private static bool Method2(CancellationToken token) 
    { 
     Thread.Sleep(3000); 

     if (token.IsCancellationRequested) 
      return false; 

     Console.WriteLine(2); 
     return true; 
    } 
} 

Как Мэтью Уотсон отмечает в комментариях, маркер отмены должен будет использоваться Method2, чтобы фактически «отменить». В моем примере он просто останавливает печать номера и возвращается раньше.

+0

Очень похоже на мой ответ - но я набрал слишком медленно.:) Я хотел бы отметить, что токен отмены должен быть фактически использован внутри метода задачи, иначе он ничего не сделает. –

+0

'cm1.Cancel();' кажется ненужным, это все еще слева направо. –

+0

@HenkHolterman Да, правда, я не видел этого из-за моего надуманного примера, делающего левый быстрее, чем правый (о, чтобы жить в более простом мире). Изменено. –

1

Использование задач, ваша логика может быть выполнена следующим образом:

System.Threading.Tasks.Task.Factory      
    .StartNew<bool>(  
     () => { return Method1(); })   
    .ContinueWith<bool>(prev =>   
     {       
      if (!prev.Result)         
       return Method2(); 
      else 
       return true;   
     }) 
    .ContinueWith(prev =>   
     {       
      // do something with prev.Result 
     }) 

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

3

Если вы не волнует, если Method2() продолжает работать после того, как method1() вернулся, это не трудно сделать что-то вроде этого:

using System; 
using System.Diagnostics; 
using System.Threading; 
using System.Threading.Tasks; 

namespace Demo 
{ 
    internal class Program 
    { 
     private void run() 
     { 
      Stopwatch sw = Stopwatch.StartNew(); 
      bool result = test(); 
      Console.WriteLine("Returned " + result + " after " + sw.Elapsed); 
     } 

     private bool test() 
     { 
      var method1 = Task.Run(new Func<bool>(Method1)); 
      var method2 = Task.Run(new Func<bool>(Method2)); 

      return method1.Result || method2.Result; 
     } 

     public bool Method1() 
     { 
      Console.WriteLine("Starting Method1()"); 
      Thread.Sleep(2000); 
      Console.WriteLine("Returning from Method1()"); 
      return true; 
     } 

     public bool Method2() 
     { 
      Console.WriteLine("Starting Method2()"); 
      Thread.Sleep(3000); 
      Console.WriteLine("Returning true from Method2()"); 
      return true; 
     } 

     private static void Main() 
     { 
      new Program().run(); 
     } 
    } 
} 

method1() занимает 2 секунды, чтобы закончить. Метод 1() занимает 3 секунды.

Когда вы запускаете это с помощью метода Method1() для возврата true, общее время составляет около 2 секунд - это время работы метода 1().

Если вы редактируете Method1() так, чтобы он возвращал false, общее время составляет около 3 секунд - время работы Method2().

Таким образом, вы можете видеть, что он не выполняет обе задачи последовательно. Этот подход является формой «спекулятивного исполнения».

Однако, если вы должны отменить Method2(), когда Method1() возвращает true, он становится более сложным.

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