我需要一个允许在后台执行方法并使窗口保持响应的功能,但我需要有可能随时停止或暂停它。我知道线程部分回答了我的问题,但不幸的是,没有办法阻止线程像那样执行一个耗时的代码块。我对流程通信有一些想法,但这是个好主意吗?或者也许有一种方法可以无条件地终止线程?
问问题
136 次
3 回答
0
如评论中所述,thread.Abort()
这是一种选择,但不建议这样做。相反,您应该使用thread.Interrupt()
,其原因在此处详述。
您不应该立即终止线程的原因是因为它可能会导致设置锁,但由于代码突然停止而没有出路,因此永远不会取消设置。因此,如果它锁定了您需要重用的代码,则无法从之前的调用中解锁它。显然,您可以围绕此进行构建,但我假设您使用的阻塞代码不是您从头开始构建的。
您可以在一个单独的进程中执行此操作,并以更小的风险终止该进程,但随后来回传递数据并且增加的混乱变得复杂。
这是使用外部进程执行此卡盘的示例,并且能够终止该进程将降低风险。
public class Main
{
public Main()
{
//In use
DoCalculation calc = new DoCalculation();
calc.StartCalculation(123, 188, ReceivedResults);
//Cancel after 1sec
Thread.Sleep(1000);
calc.CancelProcess();
}
public void ReceivedResults(string result)
{
Console.WriteLine(result);
}
}
public class DoCalculation
{
private System.Diagnostics.Process process = new System.Diagnostics.Process();
private Action<string> callbackEvent;
public void StartCalculation(int var1, int var2, Action<string> CallbackMethod)
{
callbackEvent = CallbackMethod;
string argument = "-v1 " + var1 + " -v2 " + var2;
//this is going to run a separate process that you'll have to make and
//you'll need to pass in the argument via command line args.
RunProcess("calcProc.exe", argument);
}
public void RunProcess(string FileName, string Arguments)
{
SecurityPermission SP = new SecurityPermission(SecurityPermissionFlag.Execution);
SP.Assert();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = FileName;
process.StartInfo.Arguments = Arguments;
process.StartInfo.WorkingDirectory = "";
process.OutputDataReceived += ProcessCompleted;
process.Start();
}
public void CancelProcess()
{
if (process != null)
process.Kill();
}
private void ProcessCompleted(object sender, DataReceivedEventArgs e)
{
string result = e.Data;
if (callbackEvent != null)
{
callbackEvent.Invoke(result);
}
}
}
你能告诉我们更多关于你在做什么的细节吗?也许这个问题有更好的选择。
于 2013-08-20T21:02:39.763 回答
0
看来您正在寻找BackgroundWorker。
如果主线程要求它停止,您必须检查第二个线程,并在需要时这样做。
简单(经过测试)示例:
public partial class Form1 : Form
{
BackgroundWorker w = new BackgroundWorker();
public Form1()
{
InitializeComponent();
w.WorkerSupportsCancellation = true;
w.DoWork += new DoWorkEventHandler(w_DoWork);
w.RunWorkerAsync();
}
void w_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10000000000; i++)
{
if (w.CancellationPending)
{
MessageBox.Show("Cancelled");
break;
}
//Do things...
}
}
private void button1_Click(object sender, EventArgs e)
{
w.CancelAsync();
}
}
编辑
如果您说的是 HTTP 请求,可能是:HttpWebRequest.Abort?(虽然看到这个答案。)
于 2013-08-20T20:59:20.857 回答
0
您拥有的唯一选择是,如果您始终可以在代码执行的任何时候停止代码很重要,并且当您无法在工作人员方面进行合作取消时,那么您需要有一个单独的进程。这是在您描述的庄园中停止执行代码的最可靠方法。它不能使用线程可靠地完成。
于 2013-08-20T20:48:39.027 回答