0

I'm from C background, and currently I want to make a small WinForms utility that has responsive GUI, and long running worker thread.

GUI is regular Form1 derived stuff, with progress indicators and stuff, worker thread is of kind new System.Threading.Thread();.

In C++ everything is simple, in .NET I have no clue what to do.

Is there a PostMessage kind of way for data updates? Do I kick a Timer on the main thread that reads shared lock protected structure, is there another approach? Saw multiple documents on delegates, but after 10 different articles they doesn't seem to work, maybe because I have a Worker<->GUI relation, not a GUI<->GUI relation.

All GUI stuff is in GUI class, all worker stuff is in its own worker class. What are the best practices in managed world?

Coder
  • 3,695
  • 7
  • 27
  • 42

3 Answers3

4

There are many ways, but simply,

  • Launch a thread
  • Use InvokeRequired and Invoke() to get back to GUI Thread

Also BackgroundWorker provides an easier approach.

dr. evil
  • 26,944
  • 33
  • 131
  • 201
  • If I understand correctly, then in this case data processing library owns the GUI, it does the "Update GUI now and then". What I was looking for was more like GUI<->[progress storage]<->Logic&DataLayer. Where GUI launches the DataProcessing, but checks back on events if new process storage data is available, and if it is, updates the GUI elements accordingly. Is something like that possible? – Coder Apr 14 '11 at 12:53
  • Then launch a new thread, use a shared object that can be directly accessed by GUI (so GUI can insert stuff) and the new thread. If you want you can signal thread to notify about updates, so thread would process new updates and calls Control.Invoke() to update the GUI – dr. evil Apr 14 '11 at 14:40
  • Yup, that's what I'm looking fow, but how can I signal the GUI if there is no PostMessage architecture in .NET? – Coder Apr 14 '11 at 20:08
  • All you need to do is `Control.Invoke(YourFunction)` nothing else, PostMessage etc. all happens in the background for you. – dr. evil Apr 15 '11 at 05:48
  • I tried passing a reference of `Form1` to worker, and then calling `MethodInvoker action = delegate { Form1.UpdateGUI(); }; Form1.BeginInvoke(action);`. And there is still an exception that the call is done from the wrong thread. – Coder Apr 15 '11 at 11:34
  • Found the solution: http://stackoverflow.com/questions/519233/writing-to-a-textbox-from-another-thread – Coder Apr 15 '11 at 11:44
0
  1. Use BackgroundWorker
  2. Use Control.Invoke
  3. Use SynchonizationContext
  4. Use Task Parallel Library (System.Threading.Tasks)
  5. Use Rx
  6. DO NOT USE Thread.Start or ThreadPool
Jesper
  • 7,477
  • 4
  • 40
  • 57
gandjustas
  • 1,925
  • 14
  • 12
  • It's very low level. Too low to use in programs. – gandjustas Apr 14 '11 at 10:08
  • "too low", so what? It's not assembly :) – dr. evil Apr 14 '11 at 10:17
  • Good analogy. Manually creating threads is like assembly language for parralel and asynchronous execution. – gandjustas Apr 14 '11 at 10:23
  • I'm from C/C++ background and I find low level stuff to be more productive, easier to understand. Ok, maybe it's just me, who knows. – Coder Apr 14 '11 at 11:13
  • Personally I don't use BackgroundWorker as it feels like an unnecessary layer without providing any good benefits, Thread on the other straight forward, can be launch in 2 lines of code and when it's done you just update the GUI. – dr. evil Apr 14 '11 at 14:38
  • How you determinate when it done? How you will report progress? How you will cancel backgroud evaluation when form closed or any other circumstances? How you will report failure of background process to UI? Do you know than uncatched exceptions in backgroud thread will terminate WHOLE process in .NET4? Literally you need a much more code to do this all things. It's already written in BackgroundWorker. – gandjustas Apr 14 '11 at 15:08
  • Shared variable in a work package, status::DONE + notification from worker, or Thread.Join; Shared variable in work package cancelled=true, and worker thread exits normally. Thread.Abort is "The Daily WTF" worthy; Status variable in work package workItemStatus = status::FAILED + notification from worker; Uncatched exception means your process is a toast, you REALLY don't want to salvage it!!! Are You telling BacgroundWorker does catch(Exception){/*Whistle, nothing to see, move on...*/}? – Coder Apr 15 '11 at 11:26
0

this is the program class in WinForms Application

 static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }

here there is only a single thread [STAThread]

you can use [MTAThread]instead of it so multiple threads can be handled

or can create thread a runtime using System.Threading

Nighil
  • 4,099
  • 7
  • 30
  • 56
  • Ok, but the workers are created via button clicks, so they are scheduled into thread pool or launched via thread start from Form1 interaction. So I'm still have to be in [STAThread], right? And by the way, isn't STA/MTA COM stuff? So basically since it's a GUI application, the GUI thread (the one that runs Main and later pumps Form1) has to be STA thread no matter what? – Coder Apr 14 '11 at 11:12