FileStream.EndWrite抛出异常(.NET)

时间:2010-07-21 14:07:13

标签: .net filestream

我正在尝试在复制文件时实现进度通知机制。 我是按照以下方式做到的:

  1. 我创建了两个FileStream - 用于读写
  2. 调用 BeginRead 向其传递 ReadCallback 以及包含读取流和数组的结构,以填充从文件中读取的数据。
  3. ReadCallback 中,我调用 EndRead 方法并在用于写入的文件流上调用 BeginWrite 方法传递给它 WriteCallback 以及包含流(用于写入)和要写入的数组的结构(与读取部分相同)。
  4. 当我在 WriteCallback 中调用 EndWrite 传递给它时,asyncResult会抛出 ArgumentException:IAsyncResult对象不是来自相应的异步方法在此类型上,或者使用相同的IAsyncResult
  5. 多次调用EndRead

    请帮忙解决此问题。

    更新源代码:

    private void StartAsyncCopying()
    {
        var sourceFileInfo = new FileInfo(Source);
        if (!sourceFileInfo.Exists)
        {
            throw new FileNotFoundException("File not found.",
                Source);
        }
        m_sourceLength = sourceFileInfo.Length;
        m_readerStream = new FileStream(Source, FileMode.Open);
        m_writerStream = new FileStream(Target, FileMode.Create);
        m_queueBuffer = new Queue<byte[]>(DefaultQueueBufferSize);
        m_queueBufferLock = new object();
    
        ProgressRead();
    }
    
    private void ProgressRead()
    {
        var readerChunck = new byte[DefaultChunckSize];
        var streamChunck = new StreamChunck(readerChunck, m_readerStream);
        m_readerStream.BeginRead(streamChunck.Chunck,
            0,
            streamChunck.Chunck.Length,
            ReadCallback,
            streamChunck);
    }
    
    
    private void ReadCallback(IAsyncResult asyncResult)
    {
        var streamChunck = asyncResult.AsyncState as StreamChunck;
        var numberOfBytesRead = streamChunck.Stream.EndRead(asyncResult);
    
        m_readerOffset += numberOfBytesRead;
    
        ProgressWrite(streamChunck.Chunck);
    }
    
    private void ProgressWrite(byte[] chunck)
    {
        var streamChunck = new StreamChunck(chunck, m_writerStream);
        m_writerAsyncResult = m_writerStream.BeginWrite(streamChunck.Chunck,
            0,
            streamChunck.Chunck.Length,
            WriteCallback,
            streamChunck);
    }
    
    private void WriteCallback(IAsyncResult asyncResult)
    {
        var streamChunck = asyncResult.AsyncState as StreamChunck;
        var numberOfBytesWritten = streamChunck.Stream.EndRead(asyncResult);
        m_writerOffset += numberOfBytesWritten;
    
        var progressChangedEventArgs = new CopyProgressChangedEventArgs(m_operationDescription,
            m_sourceLength,
            m_writerOffset);
        OnCopyProgressChanged(progressChangedEventArgs);
    
        if (m_writerOffset == m_sourceLength)
        {
            var copyCompletedEventArgs = new CopyCompletedEventArgs(m_operationDescription, null);
            OnCopyCompleted(copyCompletedEventArgs);
        }
        else
        {
            ProgressRead();
        }
    }
    

2 个答案:

答案 0 :(得分:4)

当您致电BeginXXX时,您可能会收到IAsyncResult个对象,要拨打EndXXX,您需要将此IAsyncResult引用传递给该方法。如果您使用了Read中的相同对象并将其传递给Write,则它将无法工作 - 在您的场景中将有两个单独的IAsyncResult对象。

当我这样做时,我将对返回的IAsyncResult的引用保留为本地类变量(如果使用回调)。当我致电EndXXX时,我会提供此本地参考(从我的初始BeginXXX获得)并在之后将其归零以表示它可以重复使用。

更新2:查看您的代码,EndWrite中的WriteCallback实际上是EndRead,野餐错误: - )

更新1:以下对我来说很好......

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication14
{
    class Program
    {
        static FileStream fs = null;
        static MemoryStream ms = null;
        static byte[] buffer = new byte[512];

        static void Main(string[] args)
        {
            fs = new FileStream("theFile", FileMode.Open);
            fs.BeginRead(buffer, 0, 512, new AsyncCallback(ReadFinished), null);

            Console.Read();
        }

        static void ReadFinished(IAsyncResult res)
        {
            fs.EndRead(res);
            fs.Dispose();

            ms = new MemoryStream();
            ms.BeginWrite(buffer, 0, 512, new AsyncCallback(WriteFinished), null);
        }

        static void WriteFinished(IAsyncResult res)
        {
            ms.EndWrite(res);
            ms.Dispose();
        }
    }
}

答案 1 :(得分:2)

你有以下内容:

private void WriteCallback(IAsyncResult asyncResult)
{
    var streamChunck = asyncResult.AsyncState as StreamChunck;
    var numberOfBytesWritten = streamChunck.Stream.EndRead(asyncResult);
                                                   ^^^^^^^

但你正在写作。你不应该打电话给EndWrite吗?或者我错过了一些非常明显的东西?

该方法中也有ProgressRead();