c# – 如何在使用BeginInvoke和EndInvoke时避免传递/存储委托?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 如何在使用BeginInvoke和EndInvoke时避免传递/存储委托?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3536字,纯文字阅读大概需要6分钟。
内容图文
![c# – 如何在使用BeginInvoke和EndInvoke时避免传递/存储委托?](/upload/InfoBanner/zyjiaocheng/812/7ef5dea8afee42a98efa365ce8babf77.jpg)
编辑:将实际问题移至顶部.
更新:发现微软的一个例子,最后隐藏了一些代码.
我的问题是这些:
>在同一个委托实例上调用多个BeginInvoke调用是否安全,或者我是否必须为每个正在进行的方法调用构建一个新的委托实例?
>如果我必须为每个实例构造新实例,是否有某种方法可以从IAsyncResult值中获取原始委托?
>是否有其他更好的方法来为我的类添加异步支持而不是使用委托?
更多信息如下.
我正在为我的一类添加异步支持,并认为我会这么做.
上这堂课:
public class Calculator
{
public Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
}
我以为我可以这样做:
public class Calculator
{
private delegate Int32 AddDelegate(Int32 a, Int32 b);
public Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
public IAsyncResult BeginAdd(Int32 a, Int32 b,
AsyncCallback callback, Object obj)
{
return new AddDelegate(Add).BeginInvoke(a, b, callback, obj);
}
public Int32 EndAdd(IAsyncResult ar)
{
return new AddDelegate(Add).EndInvoke(ar);
}
}
这不起作用,因为两个方法各自构造自己的委托对象,并且.EndInvoke调用检查以查看我调用它的委托实例是否与我最初调用BeginInvoke的实例相同.
处理这个问题的最简单方法是将引用存储到变量中,如下所示:
public class Calculator
{
private delegate Int32 AddDelegate(Int32 a, Int32 b);
private AddDelegate _Add;
public Calculator()
{
_Add = new AddDelegate(Add);
}
public Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
public IAsyncResult BeginAdd(Int32 a, Int32 b,
AsyncCallback callback, Object obj)
{
return _Add.BeginInvoke(a, b, callback, obj);
}
public Int32 EndAdd(IAsyncResult ar)
{
return _Add.EndInvoke(ar);
}
}
请注意,我完全了解允许同一个类上的多个实例方法同时执行的问题,关于共享状态等.
更新:我在Asynchronous Delegates Programming Sample上发现了这个示例.它显示将IAsyncResult引用转换回AsyncResult对象,然后我可以通过AsyncDelegate属性获取原始委托实例.
这是一种安全的方法吗?
换句话说,以下课程是否合适?
public class Calculator
{
private delegate Int32 AddDelegate(Int32 a, Int32 b);
public Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
public IAsyncResult BeginAdd(Int32 a, Int32 b, AsyncCallback callback, Object obj)
{
return new AddDelegate(Add).BeginInvoke(a, b, callback, obj);
}
public Int32 EndAdd(IAsyncResult ar)
{
AddDelegate del = (AddDelegate)((AsyncResult)ar).AsyncDelegate;
return del.EndInvoke(ar);
}
}
解决方法:
编辑:如果你只是指代表本身 – 我想你可以这样做:
public Int32 EndAdd(IAsyncResult ar)
{
var d = (AddDelegate)((AsyncResult)ar).AsyncDelegate;
return d.EndInvoke(ar);
}
你总是可以把它捕获到代表中;像这里的东西:Async without the Pain,它允许你只使用一个Action回调(或Action< T>).
其他常见模式涉及回调事件,也许还有ThreadPool.QueueUserWorkItem;比IAsyncResult简单得多.
将所有这些放在一起;这是一个示例,其中调用者和代码都不需要对IAsyncResult感到压力:
using System;
using System.Runtime.Remoting.Messaging;
public class Calculator
{
private delegate Int32 AddDelegate(Int32 a, Int32 b);
public Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
public IAsyncResult BeginAdd(Int32 a, Int32 b,
AsyncCallback callback, Object obj)
{
return new AddDelegate(Add).BeginInvoke(a, b, callback, obj);
}
public Int32 EndAdd(IAsyncResult ar)
{
var d = (AddDelegate)((AsyncResult)ar).AsyncDelegate;
return d.EndInvoke(ar);
}
}
static class Program
{
static void Main()
{
Calculator calc = new Calculator();
int x = 1, y = 2;
Async.Run<int>(
(ac,o)=>calc.BeginAdd(x,y,ac,o),
calc.EndAdd, result =>
{
Console.WriteLine(result());
});
Console.ReadLine();
}
}
static class Async
{
public static void Run<T>(
Func<AsyncCallback, object, IAsyncResult> begin,
Func<IAsyncResult, T> end,
Action<Func<T>> callback)
{
begin(ar =>
{
T result;
try
{
result = end(ar); // ensure end called
callback(() => result);
}
catch (Exception ex)
{
callback(() => { throw ex; });
}
}, null);
}
}
内容总结
以上是互联网集市为您收集整理的c# – 如何在使用BeginInvoke和EndInvoke时避免传递/存储委托?全部内容,希望文章能够帮你解决c# – 如何在使用BeginInvoke和EndInvoke时避免传递/存储委托?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。