如何立即杀死正在等待网络操作的线程?

时间:2013-12-28 21:08:52

标签: c# .net multithreading kill

所以,我正在创建一个下载管理器,我已经专门设计了每一个位,以便它可以在任何时候关闭而不给它时间清理。但是,我似乎无法找到杀死我的下载程序线程的方法。我尝试使用Thread.Abort(实际上,这是我给他们时间清理的方式:他们捕获ThreadAbortException并自己处理它),但正如你已经猜到的那样,这并不好。我会使用标志或其他东西,但是当一个线程正在等待网络操作完成时,它几乎完全被阻止了。关于如何至少中断网络操作的任何想法,以便我可以在不等待显着时间的情况下关闭?

以下是相关的代码:

try
{
    Request.AddRange(StartPosition, EndPosition);
    Owner.SetDefaultRequestParameters(Request);

    Response = Request.GetResponse() as HttpWebResponse;
    ResponseStream = Response.GetResponseStream();

    var Buffer = new Byte[Downloader.BUFFER_SIZE];

    while (true)
    {
        Paused.Wait();

        if (bStopRequested)
            break;

        int Count = ResponseStream.Read(Buffer, 0, Buffer.Length); //gets stuck here
        if (Count == 0)
            break;

        MemoryStream.Write(Buffer, 0, Count);
        Downloaded += Count;
        CurrentStreak += Count;

        if (StartPosition + Downloaded >= EndPosition)
            break;

        if (MemoryStream.Capacity - CurrentStreak < Buffer.Length)
        {
            Owner.WriteToFile(MemoryStream, StartPosition + Downloaded - CurrentStreak, CurrentStreak);
            MemoryStream.Seek(0, SeekOrigin.Begin);
            CurrentStreak = 0;
        }
    }
}
catch (ThreadAbortException)
{
    try
    {
        Response.Close();
    }
    catch { }

    return; //fastest way I have found to shut the thread down, yet
}
编辑:所以,我就是这样做的:

if (Request != null)
    Request.Abort();
if (Response != null)
    Response.Close();
ExecutionThread.Abort();

有了这个,无论线程卡在哪里(从响应流中获得响应或读取),它都会被取消并立即停止。

2 个答案:

答案 0 :(得分:2)

您可以处置ResponseStream,然后抓住ObjectDisposedException

虽然这可行,但我建议您使用CancellationToken设计应用程序以允许它正常关闭而不是中断中止线程。您还可以考虑使用async-await来使您的应用程序更具可扩展性和非阻塞性。

答案 1 :(得分:1)

不确定底层套接字的作用但是如果全部失败,您可以直接以非阻塞模式绑定到套接字,并使用Socket.BeginReceive方法,该方法将在数据到达时调用您的回调。如果你想取消当前的操作,你可以简单地调用关闭套接字就可以了。 见MSDN

  

必须通过调用完成异步BeginReceive操作   EndReceive方法。通常,该方法由   回调代表。

     

在操作完成之前,此方法不会阻止。阻止   直到操作完成,使用Receive方法之一   过载。

     

取消待处理的BeginReceive,请调用关闭方法。

您应该检查是否可以将手放在底层插座上并尝试关闭它。