c# - 如何处理调用了异步方法的对象?

标签 c# .net asynchronous dispose idisposable

我有这个实现了 IDisposable 的对象 PreloadClient,我想处理它,但是在异步方法完成它们的调用之后...这并没有发生

    private void Preload(SlideHandler slide)
    {
        using(PreloadClient client = new PreloadClient())
        {                 
             client.PreloadCompleted += client_PreloadCompleted;
             client.Preload(slide);
        }
        // Here client is disposed immediately
    }
    private void client_PreloadCompleted(object sender, SlidePreloadCompletedEventArgs e)
    {
     // this is method is called after a while, 
     // but errors are thrown when trying to access object state (fields, properties)
    }

那么,有什么想法或解决办法吗??

最佳答案

  1. 您不应该使用 using 构造,而应该在不再需要时处置您的对象:

    // keep a list of strong references to avoid garbage collection,
    // and dispose them all in case we're disposing the encapsulating object
    private readonly List<PreloadClient> _activeClients = new List<PreloadClient>();
    private void Preload(SlideHandler slide)
    {
        PreloadClient client = new PreloadClient();
        _activeClients.Add(client);
        client.PreloadCompleted += client_PreloadCompleted;
        client.Preload(slide);
    }
    
    private void client_PreloadCompleted(object sender,
         SlidePreloadCompletedEventArgs e)
    {
        PreloadClient client = sender as PreloadClient;
    
        // do stuff
    
        client.PreloadCompleted -= client_PreloadCompleted;
        client.Dispose();
        _activeClients.Remove(client);
    }
    
  2. 在这种情况下,您必须在处置主类时处置所有客户端:

    protected override Dispose(bool disposing)
    {
        foreach (PreloadClient client in _activeClients)
        { 
            client.PreloadCompleted -= client_PreloadCompleted;
            client.Dispose();
        }
        _activeClients.Clear();
        base.Dispose(disposing);
    }
    
  3. 注意这个实现不是线程安全的

    • 访问_activeClients 列表必须made thread-safe ,因为您的 PreloadCompleted 方法是从不同的线程调用的
    • 您的包含对象可能会在客户端触发事件之前被释放。在那种情况下,“做事”应该什么都不做,所以这是您应该注意的另一件事。
    • 在事件处理程序中使用 try/finally block 可能是个好主意,以确保在所有情况下都处理该对象

关于c# - 如何处理调用了异步方法的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/974945/

相关文章:

python - 带有 asyncio 的惰性迭代器(生成器)

javascript - 为什么这个 Mongoose 更新没有保存到数据库中?

c# - c#中字符串与百分比的模糊匹配

c# - 动态修改DataGrid列

c# - WebException.Response.GetResponseStream() 限制为 65536 个字符

c# - 我如何以编程方式知道代码在哪个平台下运行?

javascript - 调用具有默认参数的异步函数作为参数检查同步处理的函数?

c# - Observable.Generate 生成速度不如我预期。我错过了什么?

c# - 异步操作-MVC

.NET/MVC JSON 响应打开对话框进行保存