[英]Synchronising an Asynchronous call in c#
我在工作中遇到了一个相当尴尬的困境。 我们需要在4个或5个不同的服务中创建用户,并以这样的方式进行设置:如果一个失败,它们都会失败。 它们封装在事务范围块中。
我们需要添加用户的服务之一需要telnet,并捏造一些数据。 还有其他方法可以做到这一点(这需要花钱)但是现在这就是我们所坚持的。 添加一个用户大约需要3分钟。 我们将努力将这一点大幅度降低,这可以想象,但这不是重点。 这个调用是异步的,必须要正常工作。 一句话是,该服务最多只能有10个连接。
我们的项目正在设置为批量创建用户。 因此,一次可能创建50个用户。 当只能通过telnet建立10个连接时,这会产生一个问题,并且处理过的用户除了telnet服务之外不可能花费很长时间。 我现在需要同步这个过程,所以其余的都不能继续,直到它完成。
我们正在使用带有异步调用的回调和委托来实现该功能。 什么是封装异步部分的最佳方法,并且在完成之前不会继续?
我们应该设置一个仅在呼叫结束时终止的循环吗? 线程库中有什么东西可以帮助吗? 我之前从未使用过线程,所以这对我来说是第一次。 有什么工具可以帮助解决这个问题?
编辑:
如果我使用BeginInvoke / EndInvoke模式,那么第一个委托内的异步调用是否也会对开始/结束表示支持?
例:
public void dele1(string message) {
Console.Write(message);
delegate2 del2 = new delegate2;
del2();
Console.Write("End of Delegate 2");
}
public void dele2() {
// Long Processing
Console.Write("Delegate 2");
}
public delegate void delegate1(String message);
public delegate void delegate2();
delegate1 del1 = new delegate1(dele1);
del1("Delegate 1").BeginInvoke;
del1().EndInvoke;
Console.Write("End of Delegate 1");
//预期输出(结束调用等待代理2完成):
Delegate 1
End of Delegate 2
Delegate 2
End of Delegate 1
//或(结束调用仅等待委托1完成但不是任何内部委托调用):
Delegate 1
End of Delegate 2
End of Delegate 1
Delegate 2
结束调用会等到第二个代理完成处理吗? 或者我是否需要在所有委托调用中使用调用模式?
听起来像你想要一个队列......如果有正在进行的请求,请添加到队列中(使用Monitor
); 当呼叫完成时,检查队列......
IAsyncResult
有一个属性AsyncWaitHandle
,它为您提供一个等待句柄(如果有的话),它将在操作完成时发出信号。
因此,您可以使用WaitHandle.WaitAll
(或.WaitAny
)一次在许多句柄上执行非旋转等待。
你有几个选择。 以下是一些想法 -
首先,您可以使用ManualResetEvent来“阻止”主线程,直到您的异步操作全部完成。 想法是让主线程调用你的函数,然后执行event.WaitOne(),该函数负责设置事件。
或者,您可以尝试使用类似信号量的东西。 它旨在帮助处理这些情况,因为您可以将其限制为10次同时发生而不必担心自己会尝试处理它。 这可能是我的首选方法。
使用线程有两个原因:
使用线程的缺点是:
如果瓶颈是在远程计算机上等待3分钟,则可能值得注意的是多线程不会为您带来任何性能优势。 您可以编写整个thiing单线程,维护一组最多十个“状态机”对象并将它们移动到用户创建阶段,所有这些都来自一个线程,所有性能几乎没有差别。
因此,您可能正在寻找的是良好的可读代码布局,通过将用户创建操作转换为一系列调用,这些调用就像单个方法一样(如果您将它们作为线程运行,它们就是这样)。
获得它的另一种方法是通过迭代器方法,即包含yield return
语句,这也为您提供了单方法可读性的优势。 我必须在上周连接这三次 ! 这是Jeffrey Richter关于AsyncEnumerator的文章。
我对你如何使用TransactionScope有点不清楚(所以我可能不在基础上),但你可以创建可以发送到工作线程的DependentTransactions。 在所有DependentTransactions成功提交之后,您的顶级事务将不会提交,反之亦然。 我发现这是一种简单的方法,只要您调用的操作封装了提交/回滚功能(IEnlistmentNotification等),就可以跨线程执行全部或全部操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.