So here is my code:
class Program
{
static DispatchClass dc;
[STAThread]
static void Main(string[] args)
{
dc = new DispatchClass();
Thread th = new Thread(AccessDC);
th.Start();
Console.ReadKey();
}
private delegate void AccessDCDelegate(object state);
static private void AccessDC(object state)
{
if(dc.Dispatcher.CheckAccess())
dc.Print("hello");
else
dc.Dispatcher.Invoke(new AccessDCDelegate(AccessDC));
}
}
public class DispatchClass : DispatcherObject
{
public void Print(string str)
{
Console.WriteLine(str);
}
}
Now...the output I would expect from this is for the created thread to check the dispatcher access, see that it is on a different thread and then invoke AccessDC(...) on the original thread which then checks and sees that it is on the correct thread and calls dc.Print(...).
What actually happens is it gets to CheckAccess() and correctly sees that it isn't on the correct thread, then calls Invoke(...) and stops there.
Any insight into how Dispatchers work would be greatly appreciated.
Thanks.
The dispatcher requires a message pump, console apps do not have a message pump by default. Try running this as a GUI application instead - that will have a message pump.
CheckAccess verified that your CurrentThread DispatchClass is the current thread so it returned to you False. which is quite normal.
In this snippet of code
dc.Dispatcher.Invoke(new AccessDCDelegate(AccessDC));
You have a problem with arguments that's all.
this snippet of code works :
public partial class MainWindow : Window
{
static DispatchClass dc;
public MainWindow()
{
InitializeComponent();
dc = new DispatchClass();
Thread th = new Thread(AccessDC);
th.Start();
}
private delegate void AccessDCDelegate(object state);
static private void AccessDC(object state)
{
if (dc.Dispatcher.CheckAccess())
dc.Print("hello");
else
dc.Dispatcher.BeginInvoke(new Action(()=> AccessDC(null)));
}
}
public class DispatchClass : DispatcherObject
{
public void Print(string str)
{
MessageBox.Show(str);
}
}
Related
I have an application where I would like to execute certain orders on a certain thread when that thread is idling. So I created a manager to handle this for me, launched of a form.show and created a thread manager:
public class ThreadManager
{
static List<ThreadAble> orders = new List<ThreadAble>();
public static bool running = false;
public static void execute(ThreadAble action)
{
orders.Add(action);
}
public static void RegisterAPIThreadAndHold()
{
running = true;
Application.Idle += Application_Idle;
}
private static void Application_Idle(object sender, EventArgs e)
{
if (orders.Count != 0)
{
ThreadAble f = orders.First();
orders.Remove(f);
f.execute();
}
}
}
public interface ThreadAble {
void execute();
}
public static class formstuff{
private static void ShowDialogThreaded(){
form.Show(owner);
ThreadManager.RegisterAPIThreadAndHold();
}
}
}
I then try to use this using it by:
public class TestRegister : ThreadAble
{
public void execute()
{
throw new NotImplementedException();
}
}
ThreadManager.execute(new TestRegister());
Now this should throw an exception, however it doesn't. I have also tried with more complicated behaviour and breakpoints but this code seems to never get executed. Am I misunderstanding how the Application_Idle works? Is there another way to make it so that this thread starts executing my code (has to be this thread) when it's done with handling the GUI code and not doing anything else (it might be required to do other things a well).
I already veritfied that RegisterAPIThreadAndHold() is executed.
I have a COM object which is implemented in C#, and inherits from StandardOleMarshalObject to disable the NTA default behavior. For some reason, when I make a call to a server that makes a reentrant call to the client, the callback ends up on a different thread.
How do I ensure that all calls are made on the main thread?
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IComChat
{
void WriteLine(string text);
void Subscribe(IComChat callback);
}
public class ComChatServer : StandardOleMarshalObject, IComChat
{
private List<IComChat> Clients = new List<IComChat>();
public void WriteLine(string text)
{
foreach (var client in Clients)
{
// this makes a reentrant callback into the calling client
client.WriteLine(text);
}
}
public void Subscribe(IComChat client) => Clients.Add(client);
}
public class ComChatClient : StandardOleMarshalObject, IComChat
{
private IComChat Server;
private Thread MainThread;
public ComChatClient()
{
this.MainThread = Thread.CurrentThread;
this.Server = /* get server by some means */;
this.Server.Subscribe(this);
}
void IComChat.WriteLine(string text)
{
// this throws as the call ends up on a different thread
Contract.Assert(Thread.CurrentThread == MainThread);
Console.WriteLine(text);
}
void IComChat.Subscribe(IComChat callback) => throw new NotSupportedException();
public void WriteLine(string text) => Server.WriteLine(text);
}
public static class Program
{
public static void Main(string[] args)
{
var client = new ComChatClient();
Application.Run(new ChatWindow(client));
}
}
StandardOleMarshalObject only keeps things on the main thread if you create the object on a STA thread. Mark your entrypoint with [STAThread] to set your main thread as being single-threaded:
public static class Program
{
[STAThread]
public static void Main(string[] args)
{
var client = new ComChatClient();
Application.Run(new ChatWindow(client));
}
}
I have simple singleton class:
namespace TestApp
{
public class MySingleton
{
static MySingleton()
{
}
private static readonly MySingleton instance = new MySingleton();
private bool threadFinished = false;
public bool IsReady = false;
private MySingleton()
{
Thread t = new Thread(MyAction);
t.Start();
while (!threadFinished)
Thread.Sleep(10);
}
public static MySingleton Instance
{
get { return instance; }
}
private void MyAction()
{
threadFinished = true;
}
}
}
When I'm trying instatiate this by:
var ir = MySingleton.Instance.IsReady;
it never ends - the while loop is infinite. Why? And how to run backround thread in singleton at constructor?
You're deadlocking. You're not allowed to call any methods from another thread before the static constructor is executed. Static constructor includes the static field initalizers too.
Since you're blocking the calling thread with a while loop, static field initialization will not complete and the new thread will neither be permitted to execute MyAction either.
Your code is almost identical to this code where Eric demonstrates the deadlock.
And to quote eric's comment from same answer why does it deadlock:
#Lieven: The static constructor must run no more than once and it
must run before the first call to any static method in the class. Main
is a static method, so the main thread calls the static ctor. To
ensure it only runs once, the CLR takes out a lock that is not
released until the static ctor finishes. When the ctor starts a new
thread, that thread also calls a static method, so the CLR tries to
take the lock to see if it needs to run the ctor. The main thread
meanwhile "joins" the blocked thread, and now we have our deadlock. –
Eric Lippert Jan 17 '12 at 14:28
To answer your question; Don't do that. You gain nothing by starting a thread and waiting for it. Just simply run the method synchronously.
This works. I am not a Singleton expert - if this violates any rules, someone please point it out. But this gets around the deadlock. I copied your code into a console app, if you're using it elsewhere, adjust appropriately.
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
while (!MySingleton.Instance.IsReady)
Thread.Sleep(100);
Console.WriteLine("Done");
Console.Read();
}
}
public class MySingleton
{
static MySingleton()
{
}
private static readonly MySingleton instance = new MySingleton();
private static bool threadFinished = false;
public bool IsReady
{
get { return threadFinished; }
}
private MySingleton()
{
Thread t = new Thread(new ThreadStart(MyAction));
t.Start();
}
public static MySingleton Instance
{
get { return instance; }
}
static void MyAction()
{
threadFinished = true;
}
}
Have a look at the lock statement when you create an instance of your singleton to make it thread safe.
An example of how to use it in the singleton pattern can be found here: http://www.dofactory.com/net/singleton-design-pattern
i got this Code from an Old post
public delegate void Worker();
private static Thread worker;
public static void Init(Worker work)
{
worker = new Thread(new ThreadStart(work));
worker.Start();
}
public static void Work()
{
string result = testing;
}
I modify the code by adding parameters , when i try to call Init("AA") I am getting an error "Best overload method has some invalid arguments"
The following is the edited code
public delegate void Worker();
private static Thread worker;
public static void Init(Worker work)
{
worker = new Thread(new ThreadStart(work));
worker.Start();
}
public static void Work(string testing)
{
string result = testing;
}
Your Init method takes a delegate and you are passing a string, that is why there is no overload.
you want to do : Init(Work)
PS : your issue has nothing to do with threading.
The problem is your Worker delegate expect take a string parameter. You need to update that and then pass in the parameter e.g.
public delegate void Worker(string str);
private static Thread worker;
public static void Init(Worker work)
{
worker = new Thread(work);
worker.Start("AA");
}
public static void Work(string testing)
{
string result = testing;
}
If you want to pass some data to thread you can use ParametrizedThreadStart, or anonymous method:
private static Thread worker;
public static void Init(string testing)
{
// passing anonymous method, which will capture parameter
worker = new Thread(() => Work(testing));
worker.Start();
}
public static void Work(string testing)
{
string result = testing;
}
private static Thread worker;
public static void Init(string testing)
{
// passing PrametrizedThreadStart delegate
worker = new Thread(Work);
worker.Start(testing); // passing parameter
}
// PrametrizedThreadStart delegate accepts object as parameter
public static void Work(object testing)
{
string result = (string)testing;
}
Let's say I have an exposed interface as such:
interface IMyService
{
MyResult MyOperation();
}
This operation is synchronous and returns a value.
My implemented interface has to do the following:
Call an asynchronous method
Wait for event #1
Wait for event #2
This is due to a 3rd party COM object I am working with.
This code looks similar to the following
public MyResult MyOperation()
{
_myCOMObject.AsyncOperation();
//Here I need to wait for both events to fire before returning
}
private void MyEvent1()
{
//My Event 1 is fired in this handler
}
private void MyEvent2()
{
//My Event 2 is fired in this handler
}
My two events can happen in either order, it is quite random.
What is the proper threading mechanism I can use to synchronize this? I was using ManualResetEvent before I had to start waiting for the second event, and have not seen an easy way to use it for both events. These 2 events set variables that allow me to create the return value for MyOperation().
Any ideas on a good implementation for this? I have no control over the way the 3rd party object is implemented.
Two ManualResetEvents should do the trick for you. Just initialize them to false before you call the _myCOMObject.AsyncOperation(). Like this:
private ManualResetEvent event1;
private ManualResetEvent event2;
public MyResult MyOperation()
{
event1 = new ManualResetEvent(false);
event2 = new ManualResetEvent(false);
_myCOMObject.AsyncOperation();
WaitHandle.WaitAll(new WaitHandle[] { event1, event2 });
}
private void MyEvent1()
{
event1.Set();
}
private void MyEvent2()
{
event2.Set();
}
Edit
Thanks for the comments. I've changed the wait call to use WaitAll
My implementation example is as follows:
namespace ConsoleApplication1
{
class Program
{
private static WaitHandle[] waitHandles;
private static event EventHandler Evt1;
private static event EventHandler Evt2;
static void Main(string[] args)
{
waitHandles = new WaitHandle[]{
new ManualResetEvent(false),
new ManualResetEvent(false)
};
Evt1 += new EventHandler(Program_Evt1);
Evt2 += new EventHandler(Program_Evt2);
OnEvt1();
OnEvt2();
WaitHandle.WaitAll(waitHandles);
Console.WriteLine("Finished");
Console.ReadLine();
}
static void Program_Evt2(object sender, EventArgs e)
{
Thread.Sleep(2000);
((ManualResetEvent)waitHandles[0]).Set();
}
static void Program_Evt1(object sender, EventArgs e)
{
((ManualResetEvent)waitHandles[1]).Set();
}
static void OnEvt1()
{
if (Evt1 != null)
Evt1(null, EventArgs.Empty);
}
static void OnEvt2()
{
if (Evt2 != null)
Evt2(null, EventArgs.Empty);
}
}
}
I make it sleep for the purposes of this example and the WaitAll functionality
Cheers,
Andrew
P.S. another example would be using AsyncCallback, really quick and dirty example, but gives you more keys to open the door with :-) . Hope this helps!!
namespace ConsoleApplication1
{
class Program
{
private static WaitHandle[] waitHandles;
private static event EventHandler Evt1;
private static event EventHandler Evt2;
static void Main(string[] args)
{
waitHandles = new WaitHandle[]{
new ManualResetEvent(false),
new ManualResetEvent(false)
};
var callabck1 = new AsyncCallback(OnEvt1);
var callabck2 = new AsyncCallback(OnEvt2);
callabck1.Invoke(new ManualResetResult(null, (ManualResetEvent)waitHandles[0]));
callabck2.Invoke(new ManualResetResult(null, (ManualResetEvent)waitHandles[1]));
WaitHandle.WaitAll(waitHandles);
Console.WriteLine("Finished");
Console.ReadLine();
}
static void OnEvt1(IAsyncResult result)
{
Console.WriteLine("Setting1");
var handle = result.AsyncWaitHandle;
((ManualResetEvent)handle).Set();
}
static void OnEvt2(IAsyncResult result)
{
Thread.Sleep(2000);
Console.WriteLine("Setting2");
var handle = result.AsyncWaitHandle;
((ManualResetEvent)handle).Set();
}
}
public class ManualResetResult : IAsyncResult
{
private object _state;
private ManualResetEvent _handle;
public ManualResetResult(object state, ManualResetEvent handle)
{
_state = state;
_handle = handle;
}
#region IAsyncResult Members
public object AsyncState
{
get { return _state; }
}
public WaitHandle AsyncWaitHandle
{
get { return _handle; }
}
public bool CompletedSynchronously
{
get { throw new NotImplementedException(); }
}
public bool IsCompleted
{
get { throw new NotImplementedException(); }
}
#endregion
}
}
I am not sure I understood your question, but AutoResetEvent.WaitAll seems to solve your problem, if I got it right. It allows you to set more than one handler and it will only be released when all are set.
http://msdn.microsoft.com/en-us/library/z6w25xa6.aspx