0

I have a .NET console app, which among other things, listens for various external events (websockets, udp, etc...). When the event arrives, it does so on a worker thread. I am trying to marshal the event processing to the main thread (defined as where void Main() was kicked off).

Somewhat similar question have been asked before but it deals with calling out to Windows API. It allowed me to try out various ideas that ultimately didn't work.

I understand that to marshal threads you must have SynchronizationContext and console apps, unlike WinForms and WPF, do not have it.

I attempted to use a custom SyncronizationContext, but it just doesn't marshal threads.

So in a code like this, is it possible to Marshal execution to the main thread?

static void Main() {
  WebSocketListener.Register(ReceiveMessages);
}

static void ReceiveMessages(Message message) {
  // fires on a worker thread
  MarshalToMainThread.Post(() => ProcessOnMainThread());
}

static void ProcessOnMainThread() {

}
AngryHacker
  • 59,598
  • 102
  • 325
  • 594
  • Why not use async/await? The need for marshalling has gone down to almost nothing in all cases since `async/await`, especially in desktop applications – Panagiotis Kanavos Apr 08 '21 at 15:34
  • A good question, I imagine that you'd have to implement something similar to the "message loop" found in the main thread of Windows application. – Heinzi Apr 08 '21 at 15:36
  • Web sockets in .NET Core (like most networking classes) have asynchronous methods. There shouldn't be any need for raw threads. What is `WebSocketListener` ? – Panagiotis Kanavos Apr 08 '21 at 15:37
  • The reason you can marshal work to the main UI threads of Forms or WPF application is that those threads periodically yield and/or query for incoming messages. The main thread of a console application does not have that by default, but you could create a window handle and introduce a message loop that you could then send messages to from a background thread. – 500 - Internal Server Error Apr 08 '21 at 15:37
  • A simple example for "wait until something happens in another thread" can be found here: https://stackoverflow.com/q/3390286/87698 – Heinzi Apr 08 '21 at 15:38
  • @PanagiotisKanavos `async/await` doesn't apply here. A socket message arrives whenever so I need to process it. WebSocketListener class just handles the receipt of the message. – AngryHacker Apr 08 '21 at 15:41
  • @Heinzi That's exactly right. I do have a "message loop" of sorts. Mostly to deal with commands that user enters via Console.ReadLine. The `ManualResetEvent` object from your link might be an idea to try out. It handles the flow, though, not marshaling the execution to another thread. – AngryHacker Apr 08 '21 at 16:09
  • @500-InternalServerError When you say `window handle`, do you mean creating a hidden window? – AngryHacker Apr 08 '21 at 16:13
  • @AngryHacker that's exactly what `await` does and why all networking classes have async methods. This is no different than any web app, all of which work with `async/await`. ASP.NET Core applications *are* console applications. That's just the most basic feature though. Higher-level classes like DataFlow blocks and Channels make processing messages and creating processing pipelines a lot easier. What is WebSocketListener? There's no such library in the BCL. – Panagiotis Kanavos Apr 08 '21 at 16:13
  • 1
    @AngryHacker: Yes, exactly. – 500 - Internal Server Error Apr 08 '21 at 16:15
  • @AngryHacker the UI thread in a desktop app doesn't yield, nor does a window handle avoid blocking. Marshallinig will always block if the UI thread is busy. It's quite easy to cause deadlocks if `Invoke` is used. – Panagiotis Kanavos Apr 08 '21 at 16:15
  • 1
    @PanagiotisKanavos WebSocketListener is just wrapper around the code that handles all the websockets stuff. The code that you see just sets up a handler to receive those messages. And the message arrives when it arrives. Just cause I stick an async/await in front of it doesn't change anything - it doesn't marshal anything to the main thread. The reason for marshaling is that I need to update my console UI with information in the received message. – AngryHacker Apr 08 '21 at 16:17

0 Answers0