我已經創建了一個應用程序,它可以生成多個後臺工作人員。前提是我有一個datagridview,並且我有一個按鈕列。停止/取消BackgroundWorker
按鈕列將其名稱更改爲開始和停止。
以下是按鈕的代碼單擊
private void dgConfig_CellClick(object sender, DataGridViewCellEventArgs e)
{
// Ignore clicks that are not on button cells.
string row = e.RowIndex.ToString();
if (e.RowIndex < 0 || e.ColumnIndex > dgConfig.Columns[1].Index)
return;
if (e.ColumnIndex == 0 && dgConfig.Rows[e.RowIndex].Cells[0].Value.ToString().Equals("Start"))
{
dgConfig.Rows[e.RowIndex].Cells[0].Value = "Stop";
string input = string.Empty;
string output = string.Empty;
Dictionary<string, string> args = GenerateCommands(e.RowIndex);
dgConfig.Rows[e.RowIndex].Cells[0].Value.ToString());
StartThread(e.RowIndex.ToString(), "", "", args);
}
else if (e.ColumnIndex == 0 && dgConfig.Rows[e.RowIndex].Cells[0].Value.ToString().Equals("Stop"))
{
dgConfig.Rows[e.RowIndex].Cells[0].Value = "Start";
if (processes.Count > 0)
{
int procId = int.Parse(processes[e.RowIndex.ToString()]);
Process p = Process.GetProcessById(procId);
MessageBox.Show("Stopping Process "+p.ProcessName);
p.Close();
p = null;
}
}
}
這裏是啓動線程的方法。
private void StartThread(string row, string input, string output, Dictionary<string, string> commands)
{
BackgroundWorker background = new BackgroundWorker();
background.DoWork += new DoWorkEventHandler(bkWorker_DoWork);
background.WorkerReportsProgress = false;
background.WorkerSupportsCancellation = true;
background.RunWorkerAsync(commands);
}
最後,這是工作進程
private void bkWorker_DoWork(object sender, DoWorkEventArgs e)
{
Dictionary<string, string> inputs = e.Argument as Dictionary<string, string>;
string newcmd = @"C:\mympeg.exe";
foreach (KeyValuePair<string, string> val in inputs)
{
newcmd += " " + val.Key + " " + val.Value;
}
Process proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.RedirectStandardError = true;
proc.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler);
proc.ErrorDataReceived += new DataReceivedEventHandler(ErrorOutputHandler);
proc.Start();
processes.Add(row, proc.Id.ToString());
if (txtLog.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate {
txtLog.AppendText("Starting Process......\r\n");
txtLog.AppendText("Command recieved: "+newcmd+"\r\n");
});
}
else
{
txtLog.AppendText("Starting Process......\r\n");
txtLog.AppendText("Command recieved: " + newcmd + "\r\n");
}
StreamWriter cmdStreamWriter = proc.StandardInput;
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
cmdStreamWriter.WriteLine(newcmd);
cmdStreamWriter.Close();
proc.WaitForExit();
if (txtLog.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate { txtLog.AppendText("\r\nFinished Process.......\r\n"); });
}
else
{
txtLog.AppendText("\r\nFinished Process.......\r\n");
}
proc.Close();
}
所以,如果我開始一個長期運行的進程,進程啓動後,我試圖中止線程,但不起作用。我希望能夠停止特定的後臺工作者(不是全部)。
我可以關閉一個後臺工作人員按鈕點擊對應該行中的數據?
編輯
反正我可以做一個叫做process.WaitForEvent(方法),然後通過點擊按鈕功能呢?
我試過了,在調試器中,我可以看到它正在執行工作[key] .CancelAsyc();但RunWorkerCompleted操作未運行。這是爲什麼? – progrAmmar
正如我所說的,您還應該檢查DoWork方法中的CancellationPending標誌。當這個標記爲真時,你需要用你的道路方法自己停止工作。有關更多詳細信息,請轉至https://msdn.microsoft.com/zh-CN/library/system.componentmodel.backgroundworker.cancellationpending (v=vs.110).aspx。 – Alioza
明白了,我把它放在那裏,但我認爲這個問題是由於這個 proc.WaitForExit(); 因此,雖然工作人員可能已經取消了同步,但進程仍在運行,我想殺死該進程。一旦我殺了它,我就進入了runcomplete事件。 如何殺死WaitForExit中的進程? – progrAmmar