T
Ty
Hi guys
I hope someone can shed some light on following problem. Sorry for the
lengthy post, maybe you can read the bottom of the post to understand
my problem in advance...
We have a library that builds/manages a dataset that represents data
being received from the network.
This class looks like this (simplified):
Public class DataManager
{
private DataSet m_dataset;
private SynchronizationContext m_synchronization_context;
public DataManager()
{
m_synchronization_context = SynchronizationContext.Current; //thread
1 (gui-thread if gui-app)
//handler is the class that receives data from the network
handler.Data1Update += handle_data1update_proxy; //thread 2
handler.Data2Update += handle_data2update_proxy; //thread 3
}
private void handle_data1update(object state)
{
//doing the work on the DataSet;
}
private void handle_data2update(object state)
{
//doing the work on the DataSet;
}
private void handle_data1update_proxy(object msg)
{
object state = new object[] { msg };
m_synchronization_context.Post(handle_data1update, state);
}
private void handle_data2update_proxy(object msg)
{
object state = new object[] { msg };
m_synchronization_context.Post(handle_data2update, state);
}
}
This class/dataset is usually used in a GUI and it's working well
there. Providing thread-safety because all updating/reading is done in
the same thread.
Now we want to use the same class in a Windows Service. This is how
far i've come:
In non-gui applications there is no SynchronizationContext, causing
the DataManager-Class to not work at all. So before instanciating
DataManager, i set/create a new SyncronizationContext:
SynchronizationContext.SetSynchronizationContext(new
SynchronizationContext());
Now the DataManager works. But it crashed after a while due to Dataset-
inconsistencies. I figured out that this happens because the
SynchronizationContext-Class does not really post the message to the
main-thread, it just executes the method in the same thread as the
message came in.
and due to the async nature of Post(), it was possible that thread 2
and thread 3 delivered updates at the same time.
at this point i was able to solve the problem using a trick...:
public class CheatSync : SynchronizationContext
{
public override void Post(SendOrPostCallback d, object state)
{
Send(d, state);
}
}
i use this class to set the SyncronizationContext. By overriding Post
and doing a Send instead, the workflow is better synced. And like
that, it's actually working. But it's not satisfing.
Firstable: Send/Post are still not executing the Methods in the main-
thread, they are being executed in the thread they arrived. I'm
checking this by watching Thread.CurrentThread.ManagedThreadId, it
properly executes on the main-thread when used from a gui-app but uses
the data-incoming thread in a non-gui app.I'm shure this has potential
risks, since im reading out the data from the main-thread.
Let's assume i don't want to change DataManager-Class. How can i use
Send/Post to execute methods in other threads in non-gui applications?
i also played with instanciating WindowsFormsSynchronizationContext
and many other things.... but no success. it's either not working at
all, or not working correctly. i believe theres a "message-hub"
missing? maybe there exists some kind of smarter SyncronisationContext-
Class?
What am i missing?
THANK YOU!!
I hope someone can shed some light on following problem. Sorry for the
lengthy post, maybe you can read the bottom of the post to understand
my problem in advance...
We have a library that builds/manages a dataset that represents data
being received from the network.
This class looks like this (simplified):
Public class DataManager
{
private DataSet m_dataset;
private SynchronizationContext m_synchronization_context;
public DataManager()
{
m_synchronization_context = SynchronizationContext.Current; //thread
1 (gui-thread if gui-app)
//handler is the class that receives data from the network
handler.Data1Update += handle_data1update_proxy; //thread 2
handler.Data2Update += handle_data2update_proxy; //thread 3
}
private void handle_data1update(object state)
{
//doing the work on the DataSet;
}
private void handle_data2update(object state)
{
//doing the work on the DataSet;
}
private void handle_data1update_proxy(object msg)
{
object state = new object[] { msg };
m_synchronization_context.Post(handle_data1update, state);
}
private void handle_data2update_proxy(object msg)
{
object state = new object[] { msg };
m_synchronization_context.Post(handle_data2update, state);
}
}
This class/dataset is usually used in a GUI and it's working well
there. Providing thread-safety because all updating/reading is done in
the same thread.
Now we want to use the same class in a Windows Service. This is how
far i've come:
In non-gui applications there is no SynchronizationContext, causing
the DataManager-Class to not work at all. So before instanciating
DataManager, i set/create a new SyncronizationContext:
SynchronizationContext.SetSynchronizationContext(new
SynchronizationContext());
Now the DataManager works. But it crashed after a while due to Dataset-
inconsistencies. I figured out that this happens because the
SynchronizationContext-Class does not really post the message to the
main-thread, it just executes the method in the same thread as the
message came in.
and due to the async nature of Post(), it was possible that thread 2
and thread 3 delivered updates at the same time.
at this point i was able to solve the problem using a trick...:
public class CheatSync : SynchronizationContext
{
public override void Post(SendOrPostCallback d, object state)
{
Send(d, state);
}
}
i use this class to set the SyncronizationContext. By overriding Post
and doing a Send instead, the workflow is better synced. And like
that, it's actually working. But it's not satisfing.
Firstable: Send/Post are still not executing the Methods in the main-
thread, they are being executed in the thread they arrived. I'm
checking this by watching Thread.CurrentThread.ManagedThreadId, it
properly executes on the main-thread when used from a gui-app but uses
the data-incoming thread in a non-gui app.I'm shure this has potential
risks, since im reading out the data from the main-thread.
Let's assume i don't want to change DataManager-Class. How can i use
Send/Post to execute methods in other threads in non-gui applications?
i also played with instanciating WindowsFormsSynchronizationContext
and many other things.... but no success. it's either not working at
all, or not working correctly. i believe theres a "message-hub"
missing? maybe there exists some kind of smarter SyncronisationContext-
Class?
What am i missing?
THANK YOU!!