views:

63

answers:

2

Hello everyone. I am using API that originally was written with native code and wrapped with .net interops. The API is work asynchronic way when each operation raises event when it finished. All my logic is synchronic so I want to synchronizing the operations. I doing it with EventWaitHandle. here the code

Stock stock;

private System.Threading.EventWaitHandle _signal = null;

public void Sync()

{

        _signal = new System.Threading.EventWaitHandle(false,     
                        System.Threading.EventResetMode.AutoReset);
        MBTradingProvider.Instance.FinnishGetStoch += new 
                        EventHandler(Instance_FinnishGetStoch);
        MBTradingProvider.Instance.GetStockAsync("IBM");
        _signal.WaitOne();
}

void Instance_FinnishGetStoch(object sender, EventArgs e)

{

        stock = MBTradingProvider.Instance.CurrentWorkongStock;
        if (_signal != null)
            _signal.Set();           
}

This code stuck in the _signal.WaitOne() line, the current thread is freezes and nothing to be happened. I worked the same pattern on some other async operation and I work fine. The only difference that I can think about is that under the hood works com objects, as I said the effect that I get is that the code not responding after the WaitOne line

Anyone have an idea what can be wrong?

A: 

One issue with this code is the assignment of the _signal variable. This variable is atomically set but it is not necessarily visible between all threads involved. You need to use a method like Interlocked.Exchange to ensure the set is visible at the same time in all threads.

System.Threading.EventWaitHandle temp = new System.Threading.EventWaitHandle(false,     
                        System.Threading.EventResetMode.AutoReset);
Interolocked.Exchange(ref _signal, temp);

Also, why are you not using an AutoReset event directly?

JaredPar
Hi, I didn’t get the solution. As I understand from you the problem may be that not all the threads see my EventWaitHandle (_signal). I don’t understand how this code, the using of local "temp" EventWaitHandle, settles it? Can you explain the solution in more details? As I said I used the same code when calling different async operation and it work just fine. May be there is a difference in the async framework that is used in those two cases? Thanks.
A: 

Your code seems to be fine to me.

I am assuming the following:

  1. Sync() is executed in ThreadA
  2. Calling GetStockAsync() will create ThreadB, which will perform some task to get stock info
  3. Upon completing to get the stock info, ThreadB, not ThreadA, will execute the event handler, Instance_FinnishGetStoch(),

My rough guess is that the assumption#3 may not be true for your async framework.

You may want to try your code asynchronously and check which thread executes GetStockAsyc() and which thread executes Instance_FinishGetStock() event handler.

If only one thread does both GetStockAsync() and Instance_FinishGetStock(), your code above will be stuck on _signal.WaitOne().

For example, in a winform, if Form.BeginInoke(MyDelegate) is called in the UI thread, MyDelegate will be executed in the same UI thread, yet still asynchronously.

Chansik Im
Hi, thanks for your replay. I am running this code in win form and when I run the code asynchronously it work fine. I don’t really know which thread runs my async code but as I can operate my form while the async operation is running I am assume that it not use the UI thread. I was looking for a visualizer or external tool to view the threads that are running but haven’t managed to find on. If you can recommend one for me I will be glad.
What I am questioning is whether the event handler is being marshaled back to the UI thread or not. You can use Thread.CurrentThread.ManagedThreadId property to check the thread id. Why don't you pop up dialog boxes to show the thead id in UI thread and in the event handler? In this case, you should be able to tell whether the event handler is executed in the UI thread or not.
Chansik Im
Also, you can set a breakpoint in the event handler. Then VS debugger should tell you which thread running the event handler in Threads windows within VS debugger (Debug -> Windows -> Threads).
Chansik Im