Я думаю, что вместо использования события для настройки и продолжения цикла, я бы создал асинхронный делегат с методом обратного вызова. Когда процесс завершится, вы просто перезвоните на RunCopyScript(...)
снова. Взгляните на делегатов на MSDN и асинхронное программирование . Я уверен, что у кого-то будет способ сделать это с Action
, я просто не знаю этого достаточно хорошо, чтобы привести вам пример.
Я также видел аккуратный фрагмент о том, как получить вывод в элемент управления графическим интерфейсом из перекрестной функции. К сожалению, я не могу найти элегантный фрагмент кода, который видел раньше ... если я его наткну, я опубликую ссылку на него .
Хорошо, вот что у меня есть - для чего оно стоит. Я считаю это довольно точно. Я не ожидал, что он будет скомпилирован из коробки, так как у меня нет всех файлов, путей и т. Д. Для правильного запуска процессов. А установка имитированных командных файлов на Start()
a Process
потребует немного больше работы. Я полагаю, что вы должны быть в состоянии работать с этим и иметь что-то более близкое к тому, что вы хотите, если сделать перекрестную ссылку со ссылкой, которую я предоставил выше.
Я также прокомментировал некоторые строки кода, которые не были бы нужны, я переехал или не был распознан. Кроме того, я ничего не делал с вашим текущим try/catch
блоком.
// same signature as the method to be called asynchronously
delegate void RunScript(Int32 scriptIdx);
// declare IAsyncResult
IAsyncResult result;
Process proc = null;
private void copybutton_Click(object sender , EventArgs e)
{
InitializeBar();
nbr_of_copy_exits_ = 0;
//this.RunCopyScript(this.nbr_of_copy_exits_);
RunScript start = new RunScript(RunCopyScript);
result = start.BeginInvoke(nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc);
copybutton.Enabled = false // you don't want the button to be clicked again.
}
private void RunCopyScript(Int32 CopyScriptIdx)
{
try
{
proc = ObtainProcess(client_dest_dir_ + copy_scripts_[CopyScriptIdx]);
proc.EnableRaisingEvents = true;
//proc.Exited += new EventHandler(CopyExited);
proc.Start();
progressBar.Value = ProgressInPercent(copy_scripts_.Count() , CopyScriptIdx);
}
catch (Exception ex)
{
UpdateControl(this.toolStripStatusLabel1, "Error involving " + copy_scripts_[CopyScriptIdx] + ": " +
ex.Message);
copybutton.BackColor = Color.Red;
}
//return;
}
void CopyExited(IAsyncResult iaRes)
{
AsyncResult result = (AsyncResult)iaRes;
RunScript caller = (RunScript)result.AsyncDelegate;
Process senderProcess = (Process)iaRes.AsyncState;
caller.EndInvoke(iaRes);
if (++this.nbr_of_copy_exits_ == this.copy_scripts_.Count())
{
UpdateControl(toolStripStatusLabel1 , "Copying COMPLETE.");
copybutton.Enabled = true; // enable the button now that we're done
}
else
{
// start the process all over again
iaRes = caller.BeginInvoke(this.nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc);
}
}
private void UpdateControl(ToolStripStatusLabel tssl , String text)
{
Invoke((MethodInvoker)delegate
{
tssl.Text = text;
progressBar.Value = 0;
});
//tssl.Refresh(); 'System.Windows.Forms.ToolStripStatusLabel' does not contain a definition for 'Refresh'...
}
Как я уже говорил, существуют более элегантные реализации с использованием делегатов Action, которые, я уверен, могут быть асинхронными. Я надеюсь, что кто-то приводит пример.