C# 如何中止长时间运行的方法?

C# 如何中止长时间运行的方法?,c#,.net-4.0,process,C#,.net 4.0,Process,我有一个长时间运行的方法,我想在其中添加超时。这样做可行吗?比如: AbortWaitSeconds(20) { this.LongRunningMethod(); } 当达到20秒时,该方法将中止。该方法没有循环,我也没有对该方法的控制/代码。在后台线程中进行计算,并等待线程完成。要中止计算,请使用Thread.abort(),这将在计算线程中引发ThreadAbortException。尝试此操作 class Program { static void Main(strin

我有一个长时间运行的方法,我想在其中添加超时。这样做可行吗?比如:

AbortWaitSeconds(20)
{
    this.LongRunningMethod();
}

当达到20秒时,该方法将中止。该方法没有循环,我也没有对该方法的控制/代码。

在后台线程中进行计算,并等待线程完成。要中止计算,请使用
Thread.abort()
,这将在计算线程中引发
ThreadAbortException

尝试此操作

class Program
{
    static void Main(string[] args)
    {
        if (RunWithTimeout(LongRunningOperation, TimeSpan.FromMilliseconds(3000)))
        {
            Console.WriteLine("Worker thread finished.");
        }
        else
        {
            Console.WriteLine("Worker thread was aborted.");
        }
    }

    static bool RunWithTimeout(ThreadStart threadStart, TimeSpan timeout)
    {
        Thread workerThread = new Thread(threadStart);

        workerThread.Start();

        bool finished = workerThread.Join(timeout);
        if (!finished)
            workerThread.Abort();

        return finished;
    }

    static void LongRunningOperation()
    {
        Thread.Sleep(5000);
    }
}

您可以查看

有关通用解决方案,请参见。

只有在代码点引入检查并退出时,才能从同一线程中止长时间运行的进程。这是因为——很明显——线程很忙,所以它无法处理检查以中止自身。因此,仅包含一个对“LongRunningMethod”调用的示例无法从同一线程中止。您需要显示更多的代码,以便在这方面获得指导

一般来说,长时间运行的任务最好发送到不同的线程(例如,通过BackgroundWorker或新线程),以便可以中止它们

这里有一个简单的方法来做到这一点

private void StartThread()
{
    Thread t = new Thread(LongRunningMethod);
    t.Start();
    if (!t.Join(10000)) // give the operation 10s to complete
    {
        // the thread did not complete on its own, so we will abort it now
        t.Abort();
    }
}

private void LongRunningMethod()
{
    // do something that'll take awhile
}

由于您无法控制该代码,我认为正确的方法是使用WaitHandles和ThreadPool运行该代码:

WaitHandle waitHandle = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(<long running task delegate>), waitHandle);
WaitHandle.WaitAll(new[]{ waitHandle }, <timeout>);
WaitHandle WaitHandle=new AutoResetEvent(false);
QueueUserWorkItem(新的WaitCallback(),waitHandle);
WaitHandle.WaitAll(新[]{WaitHandle},);

您可以找到有关WaitHandle工作原理的更多信息。

您是指操作系统进程,如外部应用程序,还是指应用程序内部的某个长计算,在同一线程或其他线程中?@eugenerayabtsev long calculation在我的应用程序中,在同一线程中。需要注意的一点是,如果线程被阻塞(处于等待状态)(例如,等待套接字)它在解除阻止之前不会被中止。而且我们无法控制它何时解除阻止。这似乎是正确的。根据问题,虽然可能在主线程中执行。就像启动计时器一样,执行thread.Abort()OnTimer并捕获ThreadAbortException,感觉有点不对劲。@zespri不会永远阻塞套接字,设置套接字超时或使用套接字轮询超时,所有这些都在一个循环中。@Eugene Ryabtsev只是让OP考虑一下这不会终止“长时间运行的进程”。正确。对此表示抱歉。然后是Thread.Join()加上一个中止,如其他答案所示,应该可以解决这个问题。@JohnIsaiahCarmona:可能,但我对线程了解不多;p可能有细微的区别。现在读一下。while(t.ThreadState!=ThreadState.Running)的
是什么意思
line do?@JohnIsaiahCarmona:这只是确保线程在开始“倒计时”之前已经真正启动。假设一个线程需要20毫秒才能启动,并且将超时限制为10毫秒,线程甚至不会启动。对于更长的超时,不需要它。谢谢,我使用您的代码,但我使用的不是
AutoResetEvent
,而是
Thread.Join
。不知道它是否有任何区别。再次感谢您的帮助。:)如果调用
StartThread()
方法后我有另一行代码,它会等待10秒运行它吗?不,它只给线程10秒的时间来完成,从您调用的时间开始。Join-如果线程已经完成,不会耽搁的。