我在类库中有以下代码。我等待回到我的主应用程序中。我正在进行一个DownloadStringAsync调用,所以我必须等待几秒钟才能完成回调。我有3个这样的调用等待,所以在我的主应用程序中,我使用AutoResetEvent等待所有这些调用完成。所以我会阻塞,直到它们被设置在回调函数中。
然而,在测试后,回调不会被调用。我在想当AutoResetEvent阻止DownloadStringAsync代码时代码被阻塞。当我注释掉这段代码时,一切正常。
所以我想一旦打电话给:objNoGateway.NoGatewayStatus(sipUsername,statusDisplay1.PhoneNumber); 当代码到达这里时:handle.WaitOne(); 它将阻止类库中的代码。
非常感谢您的任何建议。
在我的类库代码示例中。
// Event handler that makes a call back in my main application
// Event handler and method that handles the event
public EventHandler<NoGatewayEventArgs> NoGatewayCompletedEvent;
// The method that raises the event.
private void OnNoGatewayCompleted(object sender, NoGatewayEventArgs e)
{
if (NoGatewayCompletedEvent != null)
{
NoGatewayCompletedEvent(this, e);
}
}
// Start the Async call to find if NoGateway is true or false
public void NoGatewayStatus(string sipUsername, string phoneNumber)
{
string strURL = string.Format("http://xxxxxxxxxxxxxxx={0}&CalledNumber={1}", sipUsername, phoneNumber);
if (!wc.IsBusy)
{
try
{
string errorMsg = string.Empty;
wc.DownloadStringAsync(new Uri(strURL));
}
catch (WebException ex)
{
Console.WriteLine("IsNoGateway: " + ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("IsNoGateway: " + ex.Message);
}
}
else
{
Console.WriteLine("WebClient: IsNoGateWay(): Busy please try again");
}
}
void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
if (e.Result == "No gateway")
{
OnNoGatewayCompleted(this, new NoGatewayEventArgs(validateResponse_e.VALIDATION_FAILED));
Console.WriteLine("NoGatway() DownloadedCompleted: " + e.Result);
}
else
{
OnNoGatewayCompleted(this, new NoGatewayEventArgs(validateResponse_e.OK));
Console.WriteLine("NoGateway() DownloadCompleted: " + e.Result);
}
}
else
{
this.OnNoGatewayCompleted(this, new NoGatewayEventArgs(validateResponse_e.SERVER_FAILED));
Console.WriteLine("No Gateway: DownloadCompleted() Error: " + e.Error.Message);
}
}
在我的主应用程序中,我注册了这个回调。并等待结果。然后设置AutoResetEvent。
ManualResetEvent[] waitValidateCallResponse = new ManualResetEvent[]
{ new ManualResetEvent(false), new ManualResetEvent(false), new ManualResetEvent(false) };
// Event handler for NoGateway event
private void OnNoGatewayCompleted(object sender, NoGatewayEventArgs e)
{
Console.WriteLine("OnNoGatewayComleted: " + e.noGateway);
waitValidateCallResponse[0].Set();
}
我打电话和阻止时的部分。
NoGateway objNoGateway = new NoGateway()
objNoGateway.NoGatewayCompletedEvent += new EventHandler<NoGatewayEventArgs>(this.OnNoGatewayCompleted);
objNoGateway.NoGatewayStatus(sipUsername, statusDisplay1.PhoneNumber);
// Block here - Wait for all reponses to finish before moving on
waitEvent.WaitOne(5000, true);
Console.WriteLine("All thread finished");
========================编辑并添加其他2个回调,以免混淆我只有一个====的问题==================
private void OnCalledNumberBlockedCompleted(object sender, CalledNumberBlockedEventArgs e)
{
Console.WriteLine("OnCalledNumberBlockedCompleted: " + e.CalledNumberBlocked);
waitValidateCallResponse[1].Set();
}
private void OnValidTelephoneNumberCompleted(object sender, ValidTelephoneNumberEventArgs e)
{
Console.WriteLine("OnValidTelephoneNumberCompleted: " + e.validTelephoneNumber);
waitValidateCallResponse[2].Set();
}
答案 0 :(得分:1)
它是否如此简单:你总是在索引0上调用Set?
private void OnNoGatewayCompleted(object sender, NoGatewayEventArgs e)
{
Console.WriteLine("OnNoGatewayComleted: " + e.noGateway);
waitValidateCallResponse[0].Set();
}
答案 1 :(得分:1)
尝试以下几点:
public void NoGatewayStatus (string sipUsername, string phoneNumber) {
string strURL = string.Format( "http://xxxxxxxxxxxxxxx={0}&CalledNumber={1}", sipUsername, phoneNumber );
ManualResetEvent wait1 = new ManualResetEvent( false );
WebClient wc = new WebClient();
Thread thr = new Thread( DownloadSomeStuff );
thr.Start( new DlArguments( strURL, wait1 ) );
// do the other three
if ( !wait1.WaitOne( 10000 ) ) {
Console.WriteLine( "DownloadSomeStuff timed out" );
return;
}
if ( !wait2.WaitOne( 10000 ) ) {
Console.WriteLine( "DownloadOtherStuff timed out" );
return;
}
if ( !wait3.WaitOne( 10000 ) ) {
Console.WriteLine( "DownloadMoreStuff timed out" );
return;
}
}
public void DownloadSomeStuff (object p_args) {
DlArguments args = (DlArguments) p_args;
try {
WebClient wc = new WebClient();
wc.DownloadString( args.Url );
args.WaitHandle.Set();
} catch ( Exception ) {
// boring stuff
}
}
private class DlArguments
{
public DlArguments (string url, ManualResetEvent wait_handle) {
this.Url = url;
this.WaitHandle = wait_handle;
}
public string Url { get; set; }
public ManualResetEvent WaitHandle { get; set; }
}
这样做吗?
答案 2 :(得分:0)
经过大量编辑后,我想我可能会理解这个问题。 Windows窗体应用程序有一个主线程;该线程用于处理消息。因此,当您的主线程阻塞时,您的应用程序无法接收事件。并且您使用WaitOne来阻止主线程。
我将WaitOne()检查移动到一个单独的计时器线程。
或者您可以等待一段有限的时间,并指示应用程序处理之间的消息:
foreach (WaitHandle handle in waitValidateCallResponse)
{
while (!handle.WaitOne(300))
Application.ProcessMessages();
Console.WriteLine("events.WaitOne(): " + handle.ToString());
}
后面的方法不是你应该在库中做的事情。我认为这是一种反模式。
答案 3 :(得分:0)
代码段是特殊的
// Event handler that makes a call back in my main application
// Event handler and method that handles the event
public EventHandler<NoGatewayEventArgs> NoGatewayCompletedEvent;
// The method that raises the event.
public void OnNoGatewayCompleted(object sender, NoGatewayEventArgs e)
{
if (NoGatewayCompletedEvent != null)
{
NoGatewayCompletedEvent(this, e);
}
}
然而,在第二个最后一个片段中,您为此事件附加了一个事件处理程序,如下所示.OnNoGatewayCompleted似乎是一个帮助方法来引发事件..(它不应该是公共的)但是这里似乎你有事件处理程序再次引发事件。除非你有2个名为OnNoGatewayCompleted的方法(我希望不是)
objNoGateway.NoGatewayCompletedEvent
+= new EventHandler<NoGatewayEventArgs>(this.OnNoGatewayCompleted);
如果您正在寻找在事件处理程序中发出信号的waitHandles,则不应将OnCalledNumberBlockedCompleted方法连接到事件上。
PS:正如Marc指出的那样..使用WaitHandle.WaitAll(for循环要求异步操作按顺序完成,可能不是这样)答案 4 :(得分:-3)
使用WaitHandle.WaitAny(handleArray);等待句柄数组中的所有句柄而不是句柄.WaitOne();在一个循环中