Apologies if this question already has an answer, but if it does, I can't find it on this site.
Firstly - this question is specific to .NET core (v1.1.0 at time of writing)
I have a third party assembly which will only handle requests made to it if they originate on the same thread. This assembly is the RabbitMQ library and details of the problem which may or may not be relevant can be found here. Basically - I have multiple threads that could potentially call this assembly - but if requests originate from different threads - an exception is thrown by it.
So - to get round this, I am attempting to create a thread which is blocked so doesn't expire - and have to somehow have all calls to this assembly processed on this thread.
My first attempt was to create an event and subscribe to the event on the blocked thread. then any other thread would begin-invoke this event, which i thought may be picked up on the correct thread so that I could fulfil my wish of having the third party assembly requests handled on the single thread.
I now (painfully so) understand that it is not possible in .NET core to begin-invoke an event in .Net core :(
Example which demonstrates the problem:
public class Program
{
public static void Main(string[] args)
{
Program program = new Program();
ManualResetEvent resetEvent = new ManualResetEvent(false);
program.StartNewThreadToBeCalled(resetEvent);
program.CallBobMultipleTimes(resetEvent);
Console.ReadLine();
}
private void CallBobMultipleTimes(ManualResetEvent resetEvent)
{
resetEvent.WaitOne();
for(int i=0 ; i<100 ; i++)
ThreadPool.QueueUserWorkItem(x=>CallBob(null, null)); //Can't BeginInvoke in .NET Core
}
private void StartNewThreadToBeCalled(ManualResetEvent resetEvent)
{
ThreadPool.QueueUserWorkItem(x=>
{
Bob bob = new Bob();
CallBob += (obj, e)=> bob.InvokeMeOnOneThreadOnly();
resetEvent.Set();
ManualResetEvent mre = new ManualResetEvent(false);
mre.WaitOne(); //Real implementation will block forever - this should be the only thread handles the processing of requests.
});
}
public event EventHandler CallBob;
}
public class Bob
{
private List<int> ThreadIdentifiers = new List<int>();
private static object SyncObject = new object();
public void InvokeMeOnOneThreadOnly()
{
lock(SyncObject)
{
int currentThreadId = Thread.CurrentThread.ManagedThreadId;
if(ThreadIdentifiers.Any())
{
if(!ThreadIdentifiers.Contains(currentThreadId))
Console.WriteLine("Don't call me from multiple threads!");
}
else
ThreadIdentifiers.Add(currentThreadId);
}
}
}
I have got this working by creating a wrapper around a concurrentQueue which notifies whenever something is added to it. I then handle this event on my special 3rd party assembly thread and pick the requests off this queue until it is exhausted... not sure why this is working when the other way wouldn't?!
Is there a better way (than the one I have found) for me to handle multiple requests from multiple different threads on a single thread in .NET core?