Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Visual Basic
  4. Synchronizing raised events to UI thread possible?

Synchronizing raised events to UI thread possible?

Scheduled Pinned Locked Moved Visual Basic
designhelpquestion
4 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Sam Marrocco
    wrote on last edited by
    #1

    I written a ProcessUtility class that allows me to call a process (which in turn runs a commandline executable) asynchronously. The process then raises events indicating completion, progress, etc. When the ProcessUtility class is set up from the UI form as: dim WithEvents P as ProcessUtility_Class P.Start All runs as expected. Events are raised appropriately and, as expected, they are on a different thread from the UI and calls to the UI controls must be invoked to avoid cross-threading errors. I've been reading up on async, synchronization contexts and other threading concepts to better understand the issues. While I can (and have) wrapped every UI call within the events, it seems very redundant to have to do it every time a UI element is utilized. Since the problem isn't really the UI, but the Asynchronous process that is raising events in the "wrong" thread to the UI, it seems that there should be a (better) way to have my ProcessUtility class raise it's events within the threading context of the UI (if desired). That way, only the few events are specialized and whatever happens within them is UI-threadsafe. Perhaps something along the lines of (pseudocode): ProcessUtility_Class Public Event Process_Started(ThisProcess as sender, SecondArg as string) Public sub Start(Form1) Form1.StartInvoke 'Everything from here until endinvoke happens within the MyForm thread RaiseEvent Process_Started(blah, blah) Form1.EndInvoke DoStuffAsynchronously End Sub Is there something like this that can be done that the raised events are always running in the context of the main form that created the ProcessUtility_Class object in the first place? My goal is to avoid having to continuously wrap every UI call with delegates and invokes.

    B L 2 Replies Last reply
    0
    • S Sam Marrocco

      I written a ProcessUtility class that allows me to call a process (which in turn runs a commandline executable) asynchronously. The process then raises events indicating completion, progress, etc. When the ProcessUtility class is set up from the UI form as: dim WithEvents P as ProcessUtility_Class P.Start All runs as expected. Events are raised appropriately and, as expected, they are on a different thread from the UI and calls to the UI controls must be invoked to avoid cross-threading errors. I've been reading up on async, synchronization contexts and other threading concepts to better understand the issues. While I can (and have) wrapped every UI call within the events, it seems very redundant to have to do it every time a UI element is utilized. Since the problem isn't really the UI, but the Asynchronous process that is raising events in the "wrong" thread to the UI, it seems that there should be a (better) way to have my ProcessUtility class raise it's events within the threading context of the UI (if desired). That way, only the few events are specialized and whatever happens within them is UI-threadsafe. Perhaps something along the lines of (pseudocode): ProcessUtility_Class Public Event Process_Started(ThisProcess as sender, SecondArg as string) Public sub Start(Form1) Form1.StartInvoke 'Everything from here until endinvoke happens within the MyForm thread RaiseEvent Process_Started(blah, blah) Form1.EndInvoke DoStuffAsynchronously End Sub Is there something like this that can be done that the raised events are always running in the context of the main form that created the ProcessUtility_Class object in the first place? My goal is to avoid having to continuously wrap every UI call with delegates and invokes.

      B Offline
      B Offline
      Bernhard Hiller
      wrote on last edited by
      #2

      What about using a BackgroundWorker for the background task? The ProgressChanged event will be sent to the correct thread, and you could use the Object userState parameter for your specific parameters. But in the end, that might create a different overhead for your events and look like just another WTF...

      S 1 Reply Last reply
      0
      • B Bernhard Hiller

        What about using a BackgroundWorker for the background task? The ProgressChanged event will be sent to the correct thread, and you could use the Object userState parameter for your specific parameters. But in the end, that might create a different overhead for your events and look like just another WTF...

        S Offline
        S Offline
        Sam Marrocco
        wrote on last edited by
        #3

        A BackgroundWorker would give similiar function, but I have several more events that BGW supports. And although I probably could inherit a class using BGW, I'd really like to learn the methodology myself and incorporate it into my objects.

        1 Reply Last reply
        0
        • S Sam Marrocco

          I written a ProcessUtility class that allows me to call a process (which in turn runs a commandline executable) asynchronously. The process then raises events indicating completion, progress, etc. When the ProcessUtility class is set up from the UI form as: dim WithEvents P as ProcessUtility_Class P.Start All runs as expected. Events are raised appropriately and, as expected, they are on a different thread from the UI and calls to the UI controls must be invoked to avoid cross-threading errors. I've been reading up on async, synchronization contexts and other threading concepts to better understand the issues. While I can (and have) wrapped every UI call within the events, it seems very redundant to have to do it every time a UI element is utilized. Since the problem isn't really the UI, but the Asynchronous process that is raising events in the "wrong" thread to the UI, it seems that there should be a (better) way to have my ProcessUtility class raise it's events within the threading context of the UI (if desired). That way, only the few events are specialized and whatever happens within them is UI-threadsafe. Perhaps something along the lines of (pseudocode): ProcessUtility_Class Public Event Process_Started(ThisProcess as sender, SecondArg as string) Public sub Start(Form1) Form1.StartInvoke 'Everything from here until endinvoke happens within the MyForm thread RaiseEvent Process_Started(blah, blah) Form1.EndInvoke DoStuffAsynchronously End Sub Is there something like this that can be done that the raised events are always running in the context of the main form that created the ProcessUtility_Class object in the first place? My goal is to avoid having to continuously wrap every UI call with delegates and invokes.

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          smarrocco wrote:

          Is there something like this that can be done that the raised events are always running in the context of the main form that created the ProcessUtility_Class object in the first place?

          You "could" pass a reference of one of the controls of the main-thread to the worker-thread. That way the control "could" do the invoke. You'd do a myForm.Invoke() from the worker-thread. ..and then you'd be tearing your hair out, trying to fix the "object is already disposed" exceptions; your thread will still be executing when the mainthread starts disposing of stuff. So, I used IlSpy to look at the code from the backgroundworker, and it's using a neat trick; AsyncOperation.Post[^] "Invokes a delegate on the thread or context appropriate for the application model." Will (probably) try it out in the weekend :) --edit There's a how-to here[^].

          Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups