1

我正在尝试异步读取 HttpResponse.GetResponseStream()

 Stream source=myHttpResponse.GetResponseStream();
 IAsyncResult asyncResult = source.BeginRead(buffer, 0, new[] { maxDownloadSize, buffer.Length }.Min(), null, null);

但由于某种原因,我的应用程序挂在 source.Endread()

int bytesRead = source.EndRead(innerAsyncResult);

我知道所有的异步调用都依赖于线程池,但是有什么办法可以杀死线程,

我确实放置了一些控件来终止异步操作

  1. 我已经放置了一个外部计时器,在触发时我正在关闭流

    System.Threading.Timer timer = new System.Threading.Timer(OnTimerCallback, source, Convert.ToInt32(new TimeSpan(0, 10, 0).TotalMilliseconds), 1); 
    
    private static void OnTimerCallback(Object state)
    {
        Stream stream = state as Stream;
    
        if (stream == null)
            return;
    
        try
        {
            stream.Close();
            stream.Dispose();
    
        }
        catch (Exception ex)
        {
            //Log Error
        }
    
        throw new Exception("Successfully closed the Stream and killing the Thread");
    }
    

    它正在关闭流,但由于某种原因,应用程序仍然挂起。

  2. 我放置了一个外部计时器,并关闭 asyncResult.AsyncWaitHandle.Close()

这两种机制似乎都是徒劳的,有什么办法可以杀死线程。

基本上我想要实现的是从 NetworkStream 读取并将其保存在 FileStream 中,它可以正常工作一段时间,后来它挂在 source.EndRead(innerAsyncResult); 从 Networkstream 读取是异步的,而将数据保存到文件流是同步的。

实际代码:

public static void CopyToStreamAsync(this Stream source, Stream destination,
    Action<Stream, Stream, Exception> completed, Action<uint> progress,
    uint bufferSize)
{
    byte[] buffer = new byte[bufferSize];

    Action<Exception> done = exception =>
        { //Completed event handler
         };

    int maxDownloadSize = maximumDownloadSize.HasValue
        ? (int)maximumDownloadSize.Value
        : int.MaxValue;

    int bytesDownloaded = 0;
    IAsyncResult asyncResult = source.BeginRead(buffer, 0, new[] { maxDownloadSize, buffer.Length }.Min(), null, null);

    Action<IAsyncResult, bool> endRead = null;
    endRead = (innerAsyncResult, innerIsTimedOut) =>
        {
            try
            {
                int bytesRead = source.EndRead(innerAsyncResult);

                int bytesToWrite = new[] { maxDownloadSize - bytesDownloaded, buffer.Length, bytesRead }.Min();

                destination.Write(buffer, 0, bytesToWrite);
                bytesDownloaded += bytesToWrite;

                if (!progress.IsNull() && bytesToWrite > 0)
                {
                   //Progress Handlers 
                }

                if (bytesToWrite == bytesRead && bytesToWrite > 0)
                {
                    asyncResult = source.BeginRead(buffer, 0, new[] { maxDownloadSize, buffer.Length }.Min(), null, null);                       
                    asyncResult.FromAsync((ia, isTimeout) => endRead(ia, isTimeout), timeout);
                }
                else
                {
                    done(null);
                }
            }
            catch (Exception exc)
            {
                done(exc);
            }
        };

    asyncResult.FromAsync((ia, isTimeout) => endRead(ia, isTimeout), timeout);
}
4

0 回答 0