上篇詳細介紹了客戶端如何發起異步調用,本篇聚焦於服務端如何以異步模式實現服務操作。這對於 I/O 密集型操作(如檔案讀取、資料庫查詢、外部 API 呼叫)至關重要,能釋放執行緒、提升服務擴展性。
在服務契約介面上,透過 [OperationContract(AsyncPattern = true)] 標記,並提供成對的 BeginXxx/EndXxx 方法:
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginDoWork(參數, AsyncCallback callback, object state);
ReturnType EndDoWork(IAsyncResult asyncResult);
範例:同步 Add 與異步 BeginAdd/EndAdd 的對照。
SyncMethod、BeginMethod、EndMethod 三個 MethodInfo。Invoke)與異步(InvokeBegin/InvokeEnd)執行介面。SyncOperationInvoker(同步)、AsyncOperationInvoker(異步)。AsyncPattern 選擇 Invoker,透過反射呼叫對應方法。[ServiceContract(Namespace = "https://www.artech.com/")]
public interface IFileReader
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginRead(string fileName, AsyncCallback callback, object state);
string EndRead(IAsyncResult asyncResult);
}
public class FileReaderService : IFileReader
{
private const string BasePath = @"E:\";
private FileStream _stream;
private byte[] _buffer;
public IAsyncResult BeginRead(string fileName, AsyncCallback callback, object state)
{
_stream = new FileStream(BasePath + fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
_buffer = new byte[_stream.Length];
return _stream.BeginRead(_buffer, 0, _buffer.Length, callback, state);
}
public string EndRead(IAsyncResult ar)
{
_stream.EndRead(ar);
_stream.Close();
return Encoding.ASCII.GetString(_buffer);
}
}
無論服務端採用同步或異步實現,客戶端生成的代理類僅暴露同步方法 Read。客戶端可自由選擇同步/異步調用方式,零感知服務端實現細節。
// 客戶端生成的介面
[ServiceContract]
public interface IFileReader
{
[OperationContract(Action="...", ReplyAction="...")]
string Read(string fileName); // 唯一的同步方法
}
// 調用簡單直接
using (var proxy = new FileReaderClient())
{
Console.WriteLine(proxy.Read("test.txt"));
}
BeginXxx/EndXxx 配對,並妥善管理非受控資源(如 FileStream)。