在 C# 上的 Web 客户端事件上取消订阅处理程序

本文关键字:取消 处理 程序 事件 上的 Web 客户端 | 更新日期: 2023-09-27 18:31:39

我想实现一个负责的方法,让我的 Web 客户端订阅处理程序,当我想取消订阅时,它似乎没有正确完成。我有一个例子:

我的函数用于订阅

private void SendRequest(Action<object, UploadStringCompletedEventArgs> callback, string url)
{
    if (!wClient.IsBusy)
    {
        wClient.UploadStringCompleted += new UploadStringCompletedEventHandler(callback);
        wClient.UploadStringAsync(new Uri(url), "POST");        
        [...]
    }
}

我的处理程序

private void wClient_request1Completed(object sender, UploadStringCompletedEventArgs e)
{
    wClient.UploadStringCompleted -= wClient_request1Completed;
    [...]
}
private void wClient_request2Completed(object sender, UploadStringCompletedEventArgs e)
{
    wClient.UploadStringCompleted -= wClient_request2Completed;
    [...]
}

我像这样使用这些方法

private WebClient wClient = new WebClient();
SendRequest(wClient_request1Completed, myUrl1);
// wClient_request1Completed(..) is run successfully
[... Request 1 is already completed ...]
SendRequest(wClient_request2Completed, myUrl2);
// wClient_request1Completed(..) and wClient_request2Completed(..) are run

你对我的问题有想法吗?非常感谢!

在 C# 上的 Web 客户端事件上取消订阅处理程序

这是因为您隐式创建了一个新委托作为SendRequest方法的参数。基本上,您当前的代码可以重写为:

// Done implicitly by the compiler
var handler = new Action<object, UploadStringCompletedEventArgs>(wClient_request1Completed); 
wClient.UploadStringCompleted += handler;
// ...
wClient.UploadStringCompleted -= wClient_request1Completed // (instead of handler)

修复它的一种方法可能是使用 UploadStringAsync 方法的有效负载参数来保留对处理程序的引用:

var handler = new UploadStringCompletedEventHandler(callback);
wClient.UploadStringCompleted += handler;
wClient.UploadStringAsync(new Uri(url), "POST", null, handler);        

然后,在UploadStringCompleted事件中:

private void wClient_request1Completed(object sender, UploadStringCompletedEventArgs e)
{
    var handler = (UploadStringCompletedEventHandler)e.UserState;
    wClient.UploadStringCompleted -= handler ;
    [...]
}

也就是说,您应该考虑切换到 HttpClient 和 async/await 编程模型,因为它会使您的代码更易于理解。