我正在尝试使用JScript.NET中的BeginRead()执行异步IO,但我无法使回调函数正常工作。
以下是代码:
function readFileAsync() {
var fs : FileStream = new FileStream( 'test.txt', FileMode.Open, FileAccess.Read );
var result : IAsyncResult = fs.BeginRead( new byte[8], 0, 8, readFileCallback ), fs );
Thread.Sleep( Timeout.Infinite );
}
var readFileCallback = function( result : IAsyncResult ) : void {
print( 'ListenerCallback():' );
}
例外是演员失败:
Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'Microsoft.JScript.Closure' to type 'System.AsyncCallback'.
at JScript 0.readFileAsync(Object this, VsaEngine vsa Engine)
at JScript 0.Global Code()
at JScript Main.Main(String[] )
我尝试过对AsyncCallback以及基本MulticastDelegate和Delegate类型进行显式转换都无济于事。
代表应该是自动创建的,无需显式创建新的AsyncCallback,例如:
BeginRead( ... new AsyncDelegate( readFileCallback), object );
事实上,如果您尝试显式创建委托,则编译器会发出错误。我必须在这里遗漏一些东西。
答案 0 :(得分:2)
问题源于内部委托是使用
创建的Delegate.CreateDelegate( Type, Object, String )
其中Type是要创建的委托类型,Object是将在其上调用方法的实例,String是方法的名称。为了使其工作,函数必须是实例方法,因此我们必须定义一个类:
class AsyncFileReader
{
function readFileAsync() {
var fs : FileStream = new FileStream(
'test.txt', FileMode.Open, FileAccess.Read
);
var result : IAsyncResult = fs.BeginRead(
new byte[8], 0, 8, ListenerCallback, fs
);
// Sleep just for testing
Thread.Sleep( Timeout.Infinite );
}
function ListenerCallback( result : IAsyncResult ) : void {
print( 'ListenerCallback():' );
}
} // class
由于回调现在可以在运行时绑定到AsyncFileReader的实例,因此转换将成功。上面列出的错误很可能是我明确投射的尝试之一,这不是转换过程中发生的错误。