基于事件和基于回调/委托的异步方法之间的区别?

Sco*_*ttG 5 wcf

在使用 svcutil.exe 时,我注意到了这个开关,/tcv:Version35。文档是这样说的:

Version35:如果要为使用 .NET Framework 3.5 的客户端生成代码,请使用 /tcv:Version35。通过使用此值,SvcUtil.exe 工具生成引用 .NET Framework 3.5 和以前版本中的功能的代码。将 /tcv:Version35 与 /async 开关一起使用时,会生成基于事件和基于回调/委托的异步方法。此外,还启用了对启用 LINQ 的数据集和 DateTimeOffset 的支持。

基于事件和基于回调/委托的异步模型有什么区别?

编辑:是一种更新/更好的方式吗?当我不使用 /tcv:Version35 开关时,我只得到 BeginXXX 和 EndXXX 方法。Silverlight 使用 XXXAsync,它告诉我应该使用基于事件的 (XXXAsync) 方法并使用此开关。

Mat*_*vis 2

让我们像这样定义一个 WCF 服务:

namespace StackOverflow
{
    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        string GetName();
    }

    public class Test : ITest
    {
        public string GetName()
        {
            return "Joel Spolsky";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果对此运行 svcutil,您将获得以下客户端定义:

public partial class TestClient : System.ServiceModel.ClientBase<ITest>, ITest
{
    // Other details elided...    

    public string GetData(int value)
    {
        return base.Channel.GetData(value);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您使用 /async 标志再次运行 svcutil,您将获得以下客户端定义:

public partial class TestClient : System.ServiceModel.ClientBase<ITest>, ITest
{
    // Other details elided...

    public event System.EventHandler<GetDataCompletedEventArgs> GetDataCompleted;

    public string GetData(int value)
    {
        return base.Channel.GetData(value);
    }

    [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
    public System.IAsyncResult BeginGetData(int value, System.AsyncCallback callback, object asyncState)
    {
        return base.Channel.BeginGetData(value, callback, asyncState);
    }

    [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
    public string EndGetData(System.IAsyncResult result)
    {
        return base.Channel.EndGetData(result);
    }

    public void GetDataAsync(int value, object userState)
    {
        if ((this.onBeginGetDataDelegate == null))
        {
            this.onBeginGetDataDelegate = new BeginOperationDelegate(this.OnBeginGetData);
        }
        if ((this.onEndGetDataDelegate == null))
        {
            this.onEndGetDataDelegate = new EndOperationDelegate(this.OnEndGetData);
        }
        if ((this.onGetDataCompletedDelegate == null))
        {
            this.onGetDataCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnGetDataCompleted);
        }
        base.InvokeAsync(this.onBeginGetDataDelegate, new object[] {value}, this.onEndGetDataDelegate, this.onGetDataCompletedDelegate, userState);
    }
}
Run Code Online (Sandbox Code Playgroud)

因此 /async 标志只是为您提供了一种与服务异步交互的方法,而不是默认的仅同步行为。

GetDataAsync() 方法异步调用 GetData() 方法,并在完成时通过 GetDataCompleted 事件通知您。

BeginGetData() 和 EndGetData() 方法使用委托的异步行为来异步调用 GetData() 方法。这类似于 System.Windows.Forms.Control 类上的 BeginInvoke() 和 EndInvoke() 方法或 System.IO.Stream 类上的 BeginRead() 和 EndRead() 方法。

  • 至于在 GetDataAsync() 和配对的 BeginGetData()/EndGetData() 之间进行选择,请记住,对 BeginGetData() 的每次调用都必须与对 EndGetData() 的调用配对。就我个人而言,我更喜欢 GetDataAsync(),因为我可以注册事件并在事件发生时处理它。 (3认同)