2013-04-05 4 views
-2

Мне нужно вызвать C dll в качестве фонового процесса. Выполнение dll занимает время, поэтому я хочу показать индикатор выполнения основного графического интерфейса. Чтобы использовать ReportProgress, мне нужно иметь возможность передавать два аргумента по ссылке и обновлять индикатор выполнения при изменении значений аргументов. Однако RunWorkerAsync, кажется, принимает значения (а не ссылки).Пропустить аргументы по ссылке BackgroundWorker

Как я могу это сделать?

Спасибо.

Вот упрощенный код:

public void button1_Click(object sender, EventArgs e) 
    { 
     //Variable declarations and initializations 

     List<object> arguments = new List<object>(); 
       arguments.Add(curgen); 
       arguments.Add(dataindex); 

     backgroundWorker1.RunWorkerAsync(arguments); 
     backgroundWorker1.ReportProgress(curgen * 100/ngen, "GEN"); 
     backgroundWorker1.ReportProgress(dataindex * 100/(DIMENSION * FITNESSCASES), "DATA"); 

    } 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     List<object> genericlist = e.Argument as List<object>; 
     // Getting variables from object 
     calldll.gpinnovization(ref curgen, ref dataindex); 
    } 

Я хочу передать 'curgen' и '' dataindex по ссылке.

+2

Можете ли вы разместить свой код? – Romoku

+0

Это, конечно, не работает, код, который называется RunWorkerAsync(), давно ушел. Простым обходным решением является обновление переменных в обработчике событий RunWorkerCompleted. –

+0

@HansPassant Как я понимаю, RunWorkerAsync() - это другой поток. Если «curgen» и «dataindex» обновляются внутри gpinnovization(), тогда ReportProgress должен обновить индикатор выполнения. Пожалуйста, дополните. – Prometheus

ответ

2

Вы можете использовать lambda для обработчика событий DoWork для закрытия переменных (обратите внимание, что закрытие закрывается над переменными, а не значениями, поэтому это не просто скопирует значение). Оттуда вы можете либо выполнить работу прямо в лямбда, либо передать переменную по ссылке другим методам.

int someValue = 5; 

BackgroundWorker worker = new BackgroundWorker(); 
worker.DoWork += (s, args) => 
{ 
    ProcessValue(ref someValue); 
}; 
worker.RunWorkerAsync(); 
+0

Но вы ничего не передаете RunWorkerAsync. Я что-то упускаю? – Prometheus

+0

@ Сунит Правильно, я нет. Я не вижу необходимости передавать что-либо «RunWorkerAsync». Когда-либо. Просто закройте значения при добавлении обработчика событий DoWork. Это проще и эффективнее. – Servy

+0

Если я хочу использовать 'someValue' в' ReportProgress', как мне это сделать? Где я должен поставить 'ProgrssChanged'? – Prometheus

-2

В интересах других, вот как я, наконец, это сделал. Благодаря Servy для предложения лямбда-выражений:

 BackgroundWorker backgroundWorker1 = new BackgroundWorker(); 
     backgroundWorker1.WorkerReportsProgress = true; 
     backgroundWorker1.DoWork += (s, args) => 
      { 
       Mydll.MyCfunction(ref curgen, ref dataindex); 
      }; 
     backgroundWorker1.RunWorkerAsync(); 
     backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged; 


     while (backgroundWorker1.IsBusy) 
     { 
      backgroundWorker1.ReportProgress(curgen * 100/ngen, "GEN"); 
      backgroundWorker1.ReportProgress(dataindex * 100/(DIMENSION * FITNESSCASES), "DATA"); 
      Application.DoEvents(); 
     } 

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e1) 
    { 
     switch (e1.UserState.ToString()) 
     { 
      case "GEN": 
       progressBar1.Value = e1.ProgressPercentage; 
       break; 
      case "DATA": 
       progressBar2.Value = e1.ProgressPercentage; 
       break; 
     } 

    } 
+0

1) Много раз вы прикрепляете обработчик событий ProgressChanged. Вы должны делать это только один раз. 2) Не используйте 'DoEvents', особенно не так. Вы не используете его должным образом. – Servy

+0

@Servy Я изменил свой ответ. Правильно ли это? Хотя он работает, я не знаю, насколько он надежный. – Prometheus

+0

Нет, у него все еще есть проблемы, о которых я уже говорил. – Servy