如何处理异步? [英] How to dispose asynchronously?

查看:202
本文介绍了如何处理异步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们说我有实现的的IDisposable 接口的类。事情是这样的:

Let's say I have a class that implements the IDisposable interface. Something like this:

MyClass的使用了一些非托管资源,因此的Dispose()的方法从的IDisposable 释放这些资源。 MyClass的应使用这样的:

MyClass uses some unmanaged resources, hence the Dispose() method from IDisposable releases those resources. MyClass should be used like this:

using ( MyClass myClass = new MyClass() ) {
    myClass.DoSomething();
}



现在,我要实现调用的 DoSomething的()的异步方法。我添加到新的方法 MyClass的

Now, I want to implement a method that calls DoSomething() asynchronously. I add a new method to MyClass:

现在,从客户端, MyClass的应使用这样的:

Now, from the client side, MyClass should be used like this:

using ( MyClass myClass = new MyClass() ) {
    myClass.AsyncDoSomething();
}

不过,如果我没有做任何事情,这可能会失败,因为对象的 MyClass的的可能之前,处置的 DoSomething的()的被称为(并抛出一个意想不到的< STRONG>的ObjectDisposedException )。因此,在调用的的Dispose()的方法(或隐性或显性)应推迟,直到异步调用的 DoSomething的()的完成。

However, if I don't do anything else, this could fail as the object myClass might be disposed before DoSomething() is called (and throw an unexpected ObjectDisposedException). So, the call to the Dispose() method (either implicit or explicit) should be delayed until the asynchronous call to DoSomething() is done.

我觉得在的处置code()的方法应该是在一个异步的方式执行,只有当所有异步调用都解决了。我想知道这可能是完成这一任务的最佳方式。

I think the code in the Dispose() method should be executed in a asynchronous way, and only once all asynchronous calls are resolved. I'd like to know which could be the best way to accomplish this.

感谢。

注:为简单起见,我还没有在Dispose()方法是如何实现的细节输入。在现实生活中我通常遵循 Dispose模式


更新:太感谢你了您的答复。我AP preciate你的努力。由于 chakrit 曾评论,我需要的倍数异步调用的DoSomething可以做成。理想情况下,这样的事情应该很好地工作:

UPDATE: Thank you so much for your responses. I appreciate your effort. As chakrit has commented, I need that multiple calls to the async DoSomething can be made. Ideally, something like this should work fine:

using ( MyClass myClass = new MyClass() ) {

    myClass.AsyncDoSomething();
    myClass.AsyncDoSomething();

}

我要学习计数信号,似乎正是我要找的。它也可以是一个设计的问题。如果我觉得方便,我将与大家分享实际案例的某些位,什么 MyClass的确实

推荐答案

所以,我的想法是要保持多少的 AsyncDoSomething()的正等待完成,只有当这个计数达到零配置。我最初的做法是:

So, my idea is to keep how many AsyncDoSomething() are pending to complete, and only dispose when this count reaches to zero. My initial approach is:

public class MyClass : IDisposable {

    private delegate void AsyncDoSomethingCaller();
    private delegate void AsyncDoDisposeCaller();

    private int pendingTasks = 0;

    public DoSomething() {
    	// Do whatever.
    }

    public AsyncDoSomething() {
    	pendingTasks++;
    	AsyncDoSomethingCaller caller = new AsyncDoSomethingCaller();
    	caller.BeginInvoke( new AsyncCallback( EndDoSomethingCallback ), caller);
    }

    public Dispose() {
    	AsyncDoDisposeCaller caller = new AsyncDoDisposeCaller();
    	caller.BeginInvoke( new AsyncCallback( EndDoDisposeCallback ), caller);
    }

    private DoDispose() {
    	WaitForPendingTasks();

    	// Finally, dispose whatever managed and unmanaged resources.
    }

    private void WaitForPendingTasks() {
    	while ( true ) {
    		// Check if there is a pending task.
    		if ( pendingTasks == 0 ) {
    			return;
    		}

    		// Allow other threads to execute.
    		Thread.Sleep( 0 );
    	}
    }

    private void EndDoSomethingCallback( IAsyncResult ar ) {
    	AsyncDoSomethingCaller caller = (AsyncDoSomethingCaller) ar.AsyncState;
    	caller.EndInvoke( ar );
    	pendingTasks--;
    }

    private void EndDoDisposeCallback( IAsyncResult ar ) {
    	AsyncDoDisposeCaller caller = (AsyncDoDisposeCaller) ar.AsyncState;
    	caller.EndInvoke( ar );
    }
}

如果两个或多个线程试图读/写可能会出现一些问题的 pendingTasks 的变量兼任,因此关键字应该用于prevent竞争条件

Some issues may occur if two or more threads try to read / write the pendingTasks variable concurrently, so the lock keyword should be used to prevent race conditions:

public class MyClass : IDisposable {

    private delegate void AsyncDoSomethingCaller();
    private delegate void AsyncDoDisposeCaller();

    private int pendingTasks = 0;
    private readonly object lockObj = new object();

    public DoSomething() {
    	// Do whatever.
    }

    public AsyncDoSomething() {
    	lock ( lockObj ) {
    		pendingTasks++;
    		AsyncDoSomethingCaller caller = new AsyncDoSomethingCaller();
    		caller.BeginInvoke( new AsyncCallback( EndDoSomethingCallback ), caller);
    	}
    }

    public Dispose() {
    	AsyncDoDisposeCaller caller = new AsyncDoDisposeCaller();
    	caller.BeginInvoke( new AsyncCallback( EndDoDisposeCallback ), caller);
    }

    private DoDispose() {
    	WaitForPendingTasks();

    	// Finally, dispose whatever managed and unmanaged resources.
    }

    private void WaitForPendingTasks() {
    	while ( true ) {
    		// Check if there is a pending task.
    		lock ( lockObj ) {
    			if ( pendingTasks == 0 ) {
    				return;
    			}
    		}

    		// Allow other threads to execute.
    		Thread.Sleep( 0 );
    	}
    }

    private void EndDoSomethingCallback( IAsyncResult ar ) {
    	lock ( lockObj ) {
    		AsyncDoSomethingCaller caller = (AsyncDoSomethingCaller) ar.AsyncState;
    		caller.EndInvoke( ar );
    		pendingTasks--;
    	}
    }

    private void EndDoDisposeCallback( IAsyncResult ar ) {
    	AsyncDoDisposeCaller caller = (AsyncDoDisposeCaller) ar.AsyncState;
    	caller.EndInvoke( ar );
    }
}

我看到这种方法的一个问题。由于资源的释放是异步完成的,这样的事情可能工作:

I see a problem with this approach. As the release of resources is asynchronously done, something like this might work:

MyClass myClass;

using ( myClass = new MyClass() ) {
    myClass.AsyncDoSomething();
}

myClass.DoSomething();

在预期的行为应该是发动的ObjectDisposedException DoSomething的()的被称为条款之外。但我不觉得这已经够糟糕重新考虑这一解决方案。

When the expected behavior should be to launch an ObjectDisposedException when DoSomething() is called outside the using clause. But I don't find this bad enough to rethink this solution.

这篇关于如何处理异步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆