【问题标题】:How to immediately kill a thread which is waiting for network operations?如何立即杀死正在等待网络操作的线程?
【发布时间】:2013-12-28 21:08:52
【问题描述】:

所以,我正在创建一个下载管理器,并且我已经专门设计了每一点,以便它可以随时关闭,而无需给它时间清理。但是,我似乎无法找到杀死我的下载线程的方法。我尝试使用 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();

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

【问题讨论】:

  • 你试过使用async/await吗?这样线程就不会在网络操作中阻塞了。
  • @BenVoigt - 解除阻塞线程和中断 I/O 不是一回事(这里)。
  • @Henk:是的,取消是一个单独的问题。无论驱动程序处理取消请求需要多长时间,资源都可能保持锁定状态。没有多少用户模式代码可以做到这一点。较新版本的 Windows 要好得多。但程序仍然可以继续执行其他操作,而不是阻止取消。
  • HttpWebRequest.Abort() 值得一试。

标签: c# .net multithreading kill


【解决方案1】:

您可以处置ResponseStream,然后捕获ObjectDisposedException

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

【讨论】:

  • 我只需要Close() 流并将 Disposing 留给正常的线程资源管理。但无论哪种方式都应该有效。而且 CancellationToken 也不能中断 I/O。
  • 不会关闭只是调用 Dispose 吗? CancellationToken 可用于许多网络调用,但不是全部。但即使你不能,你也可以添加继续“好像”你可以取消的功能。
  • Close 调用 Dispose 是否取决于流实现,我的建议是在它们不同时进行改进。在正确的地方承担正确的责任。
  • @HenkHolterman:允许Dispose 在当前卡在流的阻塞方法之一中的线程之外的线程上调用的每种流类型是否与Close 一样?跨度>
  • 从另一个线程处理不会导致多线程问题吗?我会在早上尝试并回复。
【解决方案2】:

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

异步 ​​BeginReceive 操作必须通过调用来完成 EndReceive 方法。通常,该方法由 回调委托。

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

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

你应该检查你是否可以得到底层套接字并尝试关闭它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 2010-11-09
    • 2010-11-22
    • 1970-01-01
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多