C# 删除wcf服务调用上的事件处理程序

C# 删除wcf服务调用上的事件处理程序,c#,wcf,C#,Wcf,我最近遇到了以下代码: public static class ClientBaseExtender { /// <summary> /// Tries to execute async service call. If <see cref="TimeoutException"/> occured retries again. /// </summary> /// <typeparam name="TCh

我最近遇到了以下代码:

    public static class ClientBaseExtender 
{ 
    /// <summary> 
    /// Tries to execute async service call. If <see cref="TimeoutException"/> occured retries again. 
    /// </summary> 
    /// <typeparam name="TChannel">ServiceClient class.</typeparam> 
    /// <typeparam name="TArgs">Type of service client method return argument.</typeparam> 
    /// <param name="client">ServiceClient instance.</param> 
    /// <param name="tryExecute">Delegate that execute starting of service call.</param> 
    /// <param name="onCompletedSubcribe">Delegate that subcribes an event handler to the OnCompleted event of the service client method.</param> 
    /// <param name="onCompleted">Delegate that executes when service call is succeeded.</param> 
    /// <param name="onError">Delegate that executes when service call fails.</param> 
    /// <param name="maxAttempts">Maximum attempts to execute service call before error if <see cref="TimeoutException"/> occured (by default 5).</param> 
    public static void ExecuteAsyncRepeatedly<TChannel, TArgs>(this ClientBase<TChannel> client, Action tryExecute, 
                                                               Action<EventHandler<TArgs>> onCompletedSubcribe, EventHandler<TArgs> onCompleted, 
                                                               EventHandler<TArgs> onError, int maxAttempts) 
        where TChannel : class 
        where TArgs : AsyncCompletedEventArgs 
    { 
        int attempts = 0; 
        var serviceName = client.GetType().Name; 

        onCompletedSubcribe((s, e) => 
                                { 
                                    if (e.Error == null) // Everything is OK 
                                    { 
                                        if (onCompleted != null) 
                                            onCompleted(s, e); 

                                        ((ICommunicationObject)client).Close(); 
                                        Debug.WriteLine("[{1}] Service '{0}' closed.", serviceName, DateTime.Now); 
                                    } 
                                    else if (e.Error is TimeoutException) 
                                    { 
                                        attempts++; 

                                        if (attempts >= maxAttempts) // Final timeout after n attempts 
                                        { 
                                            Debug.WriteLine("[{2}], Final Timeout occured in '{0}' service after {1} attempts.", serviceName, attempts, DateTime.Now); 

                                            if (onError != null) 
                                                onError(s, e); 
                                            client.Abort(); 

                                            Debug.WriteLine("[{1}] Service '{0}' aborted.", serviceName, DateTime.Now); 
                                            return; 
                                        } 

                                        // Local timeout 
                                        Debug.WriteLine("[{2}] Timeout occured in '{0}' service (attempt #{1}).", serviceName, attempts, DateTime.Now); 

                                        Debug.WriteLine("[{2}] Attempt #{0} to execute call to '{1}' service.", attempts + 1, serviceName, DateTime.Now); 
                                        tryExecute(); // Try again. 
                                    } 
                                    else 
                                    { 
                                        if (onError != null) 
                                            onError(s, e); 
                                        client.Abort(); 
                                        Debug.WriteLine("[{1}] Service '{0}' aborted.", serviceName, DateTime.Now); 
                                    } 
                                }); 

        Debug.WriteLine("[{2}] Attempt #{0} to execute call to '{1}' service.", attempts + 1, serviceName, DateTime.Now); 
        tryExecute(); // First attempt to execute 
    } 
}

    public void GetData()
    {
    var client = new MyServiceClient(); 
     client.ExecuteAsyncRepeatedly(() => client.MyOperationAsync(...), 
    (EventHandler<MyOperationCompletedEventArgs> handler)                                        =>client.MyOperationCompleted += handler, 
    (s, e) => // OnCompleted 
        { 
            Do(e.Result); 
        }, 
    (s, e) => // OnError 
        { 
            HandleError(e.Error); 
        } 
); 

我认为可以通过在代码中实现推拉策略来解决这个问题。我提出类似的建议:

 bool _requestPending;
 readonly object _lock = new object();

 void OnClick (...)
 {
     lock(_lock)
     {
        if (_requestPending == false)
        {
            _dataService.GetData(GetDataCompleted);
            _requestPending = true;
        }
     }
 }
 private void GetDataComplete(Data data)
 {
     lock(_lock)
     {
        try
        {
           //do something with data 
        }
        finally
        {
           _requestPending = false;
        }  
     }           
 }
更好的是,当您有一个挂起的请求时,禁用UI按钮。从不同线程访问和修改_requestPending不会有任何并发性问题,但如果服务响应足够快,仍然可能会出现争用情况,因此最好同步两个代码块

不管怎样,就我个人而言,我不喜欢你试图实现的这个实现。代码非常混乱,并且很难预见可能出现的问题。确保:

  • 您提供了一种中止请求的方法 然后再次启用按钮

  • 更新屏幕的代码是 由UI线程执行


我建议修复该代码块,其中一半未标记为代码。在突出显示代码块后使用010101图标。可以在按钮单击处理程序所在的位置添加实际代码吗?这里没有足够的信息来确定为什么要多次添加该处理程序。我不知道你的意思,看起来代码在我的代码块中正确显示。steve,请在我上面的编辑中查看我对代码的使用情况。谢谢你的帮助!
 bool _requestPending;
 readonly object _lock = new object();

 void OnClick (...)
 {
     lock(_lock)
     {
        if (_requestPending == false)
        {
            _dataService.GetData(GetDataCompleted);
            _requestPending = true;
        }
     }
 }
 private void GetDataComplete(Data data)
 {
     lock(_lock)
     {
        try
        {
           //do something with data 
        }
        finally
        {
           _requestPending = false;
        }  
     }           
 }