0

我需要一个允许在后台执行方法并使窗口保持响应的功能,但我需要有可能随时停止或暂停它。我知道线程部分回答了我的问题,但不幸的是,没有办法阻止线程像那样执行一个耗时的代码块。我对流程通信有一些想法,但这是个好主意吗?或者也许有一种方法可以无条件地终止线程?

4

3 回答 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 回答