2015-03-01 4 views
1

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

Это то, что я пробовал, и это не совсем то, что моя программа выглядит, но я упростил ее, чтобы свести к минимуму путаницу.

class Program 
{ 
    static int[] data = new int[10] 
    { 
     1, 2, 3, 4, 5, 6, 7, 8, 9, 10 
    }; 

    static void Main(string[] args) 
    { 
     Method(0); 
    } 

    static void Method(int parameter) 
    { 
     if (parameter < data.Length) 
     { 
      Worker worker = new Worker(); 
      worker.OnProgressChange += delegate 
      { 
       // Update UI 
      }; 
      worker.OnWorkComplete += delegate 
      { 
       Method(parameter++); 
      }; 
      worker.DoWork(); 
     } 
    } 
} 

class Worker 
{ 
    public event EventHandler OnProgressChange; 
    public event EventHandler OnWorkComplete; 

    public Worker() { } 

    public void DoWork() { } 
} 

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

+0

Я не понял ваш вопрос, но я думаю, что ваш ответ иллюстрирует то, чего вы пытаетесь достичь. Вы хотите сделать тяжелую обработку (конвертирование коллекции файлов), которая займет некоторое время. Вы хотите, чтобы поток выполнения вашего приложения поддерживался до завершения обработки файлов, но вы хотите, чтобы Windows реагировала. Это верно? – mbeckish

+0

@mbeckish Я хочу, чтобы поток пользовательского интерфейса был активным и незамерзающим. Имея это в виду, я пытаюсь преобразовать список файлов, но только по одному. Это то, что я пытаюсь сделать. – Minato

ответ

0

Хорошо, я нашел решение! Ответ не будет применяться к абстрагированному сценарию, который я привел выше, но идея такая же.

private bool flag = false; 

    private void CheckCompletion() 
    { 
     // Do stuff 

     ConvertFiles(); 
     while (!flag) 
      Application.DoEvents(); 

     // Do more stuff 
    } 

    private void ConvertFiles() 
    { 
     UpdateStatus("Converting...", true); 
     Task.Factory.StartNew(() => 
     { 
      using (Engine engine = new Engine()) 
      { 
       for (int i = 0; i < entries.Count; i++) 
       { 
        MediaFile inputFile = new MediaFile(entries[i].FilePath); 
        MediaFile outputFile = new MediaFile(entries[i].FilePath.Replace(".aac", ".mp3")); 
        engine.ConvertProgressEvent += (obj, args) => 
        { 
         int value = (int)Math.Round(args.ProcessedDuration.TotalSeconds/
          args.TotalDuration.TotalSeconds); 
         Invoke(new Action(delegate { entries[i].ProgressBarEx.Value = value; })); 
        }; 
        engine.Convert(inputFile, outputFile); 
       } 
      } 
      flag = true; 
     }); 
    } 

Если вам необходимо выполнить синхронный метод асинхронно, используйте параллельную библиотеку задач. Если вам нужно запустить несколько экземпляров этой асинхронной синхронной задачи, но только по одному, поместите for loop внутри этой задачи и укажите переменную bool, чтобы сообщить приложению, когда все задачи завершены. Это while(!flag) Application.DoEvents();, что является чистой магией.

Прошу прощения, если что-либо из того, что я сказал, было слишком запутанным.

+1

Это не похоже на хороший способ сделать это. У вас ограниченный цикл while, который будет продолжать получать свой временной срез снова и снова, чтобы уступить системе. .NET обеспечивает лучшие встроенные способы решения этой проблемы. – mbeckish

+0

@mbeckish Я не могу сказать, что это хороший способ сделать это. Но это был единственный способ, которым я мог придумать. Пожалуйста, если у вас есть идея лучше, дайте мне знать! Причина, по которой я задал этот вопрос на SO, заключалась не только в том, чтобы получить способ сделать это, но и убедиться, что метод, который я реализовал, был хорошим методом. – Minato

0

.NET уже сделал это для вас: BackgroundWorker Class

В основном все, что вам нужно сделать, это изменить параметры метода ограничится BackgroundWorker (object sender, DoWorkEventArgs e) и вызвать RunWorkAsync

+0

Введен образец кода (лучше Fibonacci :) – supertopi

+0

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

+0

Хахахаха, если вы понимаете, что я имею в виду. – Minato

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