【发布时间】:2016-08-09 23:50:21
【问题描述】:
我对 C# 非常陌生,并试图了解后台工作人员。
目前,当我运行此代码时,它会在单击 StopButton 后停止重定向并从命令提示符读取输出,并留下“已取消”消息,但之后什么也不做。我目前可能实现这一切都是错误的,但我通过单击调用 CancelAsync() 的停止按钮设置了 e.Cancel,这将 CancellationPending = true。有人对我应该如何处理有任何想法吗?
非常感谢!! 感谢您的帮助!
public Form2()
{
InitializeComponent();
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
private void StopButton_Click(object sender, EventArgs e)
{
if (bw.WorkerSupportsCancellation == true)
{
bw.CancelAsync();
bw.Dispose();
Invoke(new ToDoDelegate(() => this.textBox2.Text += Environment.NewLine + "Cancelled " + Environment.NewLine));
}
}
private void Submit_Click(object sender, EventArgs e)
{
if(bw.IsBusy != true)
{
bw.RunWorkerAsync();
Invoke(new ToDoDelegate(() => this.textBox2.Text += "Starting Download " + Environment.NewLine));
}
}
public bool DoSVNCheckout(String KeyUrl, DoWorkEventArgs e)
{
SVNProcess = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/C plink download files using svn"
Verb = "runas",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = false,
}
};
SVNProcess.Start();
while(!SVNProcess.StandardOutput.EndOfStream & bw.CancellationPending == false)
{
string output = SVNProcess.StandardOutput.ReadLine();
Invoke(new ToDoDelegate(() => this.textBox2.Text += output));
}
while (!SVNProcess.StandardError.EndOfStream & bw.CancellationPending == false)
{
string Erroutput = SVNProcess.StandardError.ReadLine();
Invoke(new ToDoDelegate(() => this.textBox2.Text += Erroutput));
}
if(SVNProcess.StandardError.EndOfStream & bw.CancellationPending == false)
{
string Erroutput = SVNProcess.StandardError.ReadLine();
Invoke(new ToDoDelegate(() => this.textBox2.Text += Erroutput));
}
//if I manually close the cmd.exe window by clicking X
//in the top right corner the program runs correctly
//at these lines of code right here
if(bw.CancellationPending == true)
{
e.Cancel = true;
return true;
}
return false;
}
private delegate void ToDoDelegate();
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if(bw.CancellationPending == true)
{
e.Cancel = true;
return;
}
e.Cancel = DoSVNCheckout(URL, e);
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
this.textBox2.Text = "Canceled!";
}
else{
this.textBox2.Text = "Done!";
}
}
【问题讨论】:
-
我看不出这是异步的。这只是多线程。看看CancellationTokenSource。
-
你是说我不应该使用命令“CancelAsync()”吗?该命令似乎确实停止了当前操作,但之后什么也不做。
-
我是说考虑使用 CancellationTokenSource 和 CancellationToken。这正是它的设计目的。
-
@Felix:也许你可以详细说明。 IME,
CancellationToken很有用,如果有一个 CPU 绑定操作可以定期检查取消(例如调用ThrowIfCancellationRequested())以一种可靠的方式。但在这种情况下,当前进程只是在等待它启动的外部进程;恕我直言,设置某种循环只是为了轮询令牌似乎不如例如有用。创建一个TaskCompletionSource来表示用户的异步输入(请参阅我提出的答案)。 -
@Felix:但是如果您知道更好的方法,可以更直接、更简洁地集成
CancellationToken,我鼓励您提供这些细节,因为它们会非常有用。
标签: c# asynchronous process backgroundworker