什么是AsyncCallback?

84
什么是AsyncCallback,为什么我们需要使用它?
3个回答

146
async方法完成处理时,将自动调用AsyncCallback方法,在其中可以执行后处理语句。使用这种技术,无需轮询或等待async线程完成。
下面是有关Async回调用法的更多解释: 回调模型:回调模型要求我们指定要回调的方法,并包括在回调方法中需要完成调用的任何状态。回调模型可以在以下示例中看到:
static byte[] buffer = new byte[100];

static void TestCallbackAPM()
{
    string filename = System.IO.Path.Combine (System.Environment.CurrentDirectory, "mfc71.pdb");

    FileStream strm = new FileStream(filename,
        FileMode.Open, FileAccess.Read, FileShare.Read, 1024,
        FileOptions.Asynchronous);

    // Make the asynchronous call
    IAsyncResult result = strm.BeginRead(buffer, 0, buffer.Length,
        new AsyncCallback(CompleteRead), strm);
}

在这个模型中,我们正在创建一个新的AsyncCallback委托,指定在操作完成时(在另一个线程上)要调用的方法。此外,我们还指定了一些可能需要作为调用状态的对象。对于这个示例,我们将流对象发送进去,因为我们需要调用EndRead并关闭流。
我们创建的要在调用结束时调用的方法可能是这样的:
static void CompleteRead(IAsyncResult result)
{
    Console.WriteLine("Read Completed");

    FileStream strm = (FileStream) result.AsyncState;

    // Finished, so we can call EndRead and it will return without blocking
    int numBytes = strm.EndRead(result);

    // Don't forget to close the stream
    strm.Close();

    Console.WriteLine("Read {0} Bytes", numBytes);
    Console.WriteLine(BitConverter.ToString(buffer));
}

其他技术包括等待完成轮询

等待完成模型等待完成模型允许您启动异步调用并执行其他工作。一旦其他工作完成,您可以尝试结束调用,并阻塞直到异步调用完成。

// Make the asynchronous call
strm.Read(buffer, 0, buffer.Length);
IAsyncResult result = strm.BeginRead(buffer, 0, buffer.Length, null, null);

// Do some work here while you wait

// Calling EndRead will block until the Async work is complete
int numBytes = strm.EndRead(result);

或者你可以使用等待句柄(wait handles)。

result.AsyncWaitHandle.WaitOne();

轮询模式 轮询方法类似,唯一的区别是代码将轮询IAsyncResult以查看它是否已完成。

// Make the asynchronous call
IAsyncResult result = strm.BeginRead(buffer, 0, buffer.Length, null, null);

// Poll testing to see if complete
while (!result.IsCompleted)
{
    // Do more work here if the call isn't complete
    Thread.Sleep(100);
}

1
有没有一种方法可以使CompleteRead成为非静态函数? - greggorob64
1
是的,您可以将TestCallbackAPM和CompleteRead都制作为实例方法。 - Rashmi Pandit

32

这样想。你有一些想要并行执行的操作。你可以使用线程来实现异步执行。这是一种“发射并忘记”的机制。

但有些情况需要在发射并忘记的同时,需要在操作完成时得到通知。为此,你可以使用异步回调。

该操作是异步的,但会在操作完成时回调你。这样做的优点是,你不必等待操作完成。你可以自由地执行其他操作,因此你的线程不会被阻塞。

例如,后台传输大文件。当传输正在进行时,你可能不想阻止用户执行其他操作。一旦传输完成,进程将在异步方法上回调你,在那里你可以弹出一个消息框,显示“传输完成”。


4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接