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. C#
  4. Having an issue accessing a bitmap region from two different threads.

Having an issue accessing a bitmap region from two different threads.

Scheduled Pinned Locked Moved C#
graphicshelptutorial
3 Posts 2 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.
  • H Offline
    H Offline
    Herboren
    wrote on last edited by
    #1

    I can't for the life of me figure out how to access the region from a tick thread which is calling a bgworker(). Here is the original code

    private void t_processFrame_Tick(object sender, EventArgs e)
    {
    if (!_bw_frameProcessor.IsBusy)
    {
    _bw_frameProcessor.RunWorkerAsync();
    }
    }

    private void _bw_frameProcessor_DoWork(object sender, DoWorkEventArgs e)
    {
    try
    {
    GetImage = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
    g = Graphics.FromImage(GetImage);
    g.CopyFromScreen(screen.Bounds.X, 0, 0, 0, GetImage.Size);

        pbDesktopFeed.Image = (Bitmap)GetImage;                           
        motionDetector.ProcessFrame((Bitmap)pbDesktopFeed.Image);
    }
    catch (Exception ex) { }
    

    }

    Its kind of frustrating because I have been sitting here for 3 days (I have a high tolerance of trying different variations before I burn myself out) trying to figure out why it works fine in Timer_Tick but not when Timer) Tick is running the Backgroundworker. My guess is that it is because of the Threads between the both. I have tried cloning the bitmap inside the background worker

    GetImage = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
    Bitmap clone = (Bitmap) GetImage.Clone()
    g = Graphics.FromImage(clone);
    g.CopyFromScreen(screen.Bounds.X, 0, 0, 0, clone.Size);
    pbDesktopFeed.Image = (Bitmap)GetImage;
    motionDetector.ProcessFrame((Bitmap)pbDesktopFeed.Image);

    I have tried cloning the image using AForge:

    GetImage = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
    g = Graphics.FromImage(GetImage );
    g.CopyFromScreen(screen.Bounds.X, 0, 0, 0, GetImage .Size);
    pbDesktopFeed.Image = (Bitmap)GetImage;
    motionDetector.ProcessFrame(AForge.Imaging.Image.Clone((Bitmap)pbDesktopFeed.Image));

    This however, works fine when I drop it all into the Timer_Tick event.

    private void t_processFrame_Tick(object sender, EventArgs e)
    {
    try
    {
    GetImage = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
    g = Graphics.FromImage(GetImage);
    g.CopyFromScreen(screen.Bounds.X, 0, 0, 0, GetImage.Size);

        pbDesktopFeed.Image = (Bitmap)GetImage;
        motionDetector.ProcessFrame((Bitmap)pbDesktopFeed.Image);
    }
    catch (Exception ex) { }
    

    }

    OriginalGriffO 1 Reply Last reply
    0
    • H Herboren

      I can't for the life of me figure out how to access the region from a tick thread which is calling a bgworker(). Here is the original code

      private void t_processFrame_Tick(object sender, EventArgs e)
      {
      if (!_bw_frameProcessor.IsBusy)
      {
      _bw_frameProcessor.RunWorkerAsync();
      }
      }

      private void _bw_frameProcessor_DoWork(object sender, DoWorkEventArgs e)
      {
      try
      {
      GetImage = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
      g = Graphics.FromImage(GetImage);
      g.CopyFromScreen(screen.Bounds.X, 0, 0, 0, GetImage.Size);

          pbDesktopFeed.Image = (Bitmap)GetImage;                           
          motionDetector.ProcessFrame((Bitmap)pbDesktopFeed.Image);
      }
      catch (Exception ex) { }
      

      }

      Its kind of frustrating because I have been sitting here for 3 days (I have a high tolerance of trying different variations before I burn myself out) trying to figure out why it works fine in Timer_Tick but not when Timer) Tick is running the Backgroundworker. My guess is that it is because of the Threads between the both. I have tried cloning the bitmap inside the background worker

      GetImage = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
      Bitmap clone = (Bitmap) GetImage.Clone()
      g = Graphics.FromImage(clone);
      g.CopyFromScreen(screen.Bounds.X, 0, 0, 0, clone.Size);
      pbDesktopFeed.Image = (Bitmap)GetImage;
      motionDetector.ProcessFrame((Bitmap)pbDesktopFeed.Image);

      I have tried cloning the image using AForge:

      GetImage = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
      g = Graphics.FromImage(GetImage );
      g.CopyFromScreen(screen.Bounds.X, 0, 0, 0, GetImage .Size);
      pbDesktopFeed.Image = (Bitmap)GetImage;
      motionDetector.ProcessFrame(AForge.Imaging.Image.Clone((Bitmap)pbDesktopFeed.Image));

      This however, works fine when I drop it all into the Timer_Tick event.

      private void t_processFrame_Tick(object sender, EventArgs e)
      {
      try
      {
      GetImage = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
      g = Graphics.FromImage(GetImage);
      g.CopyFromScreen(screen.Bounds.X, 0, 0, 0, GetImage.Size);

          pbDesktopFeed.Image = (Bitmap)GetImage;
          motionDetector.ProcessFrame((Bitmap)pbDesktopFeed.Image);
      }
      catch (Exception ex) { }
      

      }

      OriginalGriffO Offline
      OriginalGriffO Offline
      OriginalGriff
      wrote on last edited by
      #2

      It's probably pretty simple: only code that is running on the main (UI) thread can access any control in any way: since you moved it to a BackgroundWorker it isn't running on that thread any more, so when you try to access the Image or similar it's failing with an exception. Start by adding a try...catch block with Debug.WriteLine statements to check that and consider either Invoking the relevant controls or moving the Control related code back to the UI thread via the Progress reporting mechanism of the BackgroundWorker.

      "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!

      "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
      "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt

      H 1 Reply Last reply
      0
      • OriginalGriffO OriginalGriff

        It's probably pretty simple: only code that is running on the main (UI) thread can access any control in any way: since you moved it to a BackgroundWorker it isn't running on that thread any more, so when you try to access the Image or similar it's failing with an exception. Start by adding a try...catch block with Debug.WriteLine statements to check that and consider either Invoking the relevant controls or moving the Control related code back to the UI thread via the Progress reporting mechanism of the BackgroundWorker.

        "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!

        H Offline
        H Offline
        Herboren
        wrote on last edited by
        #3

        Turns out it was as simple as creating a public void PreviewImageUpdate() outside of the bg worker

        private void t_processFrame_Tick(object sender, EventArgs e) {
        // UpdateMotionDetectionPreviiw();
        if (!_bw_frameProcessor.IsBusy) {
        _bw_frameProcessor.RunWorkerAsync();
        }
        }

        private void _bw_frameProcessor_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
        _bw_frameProcessor.Dispose();
        }

        private void _bw_frameProcessor_DoWork(object sender, DoWorkEventArgs e) {
        UpdateMotionDetectionPreview();
        }

        public void UpdateMotionDetectionPreview() {
        try {
        GetImage = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
        g = Graphics.FromImage(GetImage);
        g.CopyFromScreen(screen.Bounds.X, 0, 0, 0, GetImage.Size);

        if (motionDetector.ProcessFrame(GetImage) > 1.02 f)
          pbDesktopFeed.Image = GetImage;
        else
          pbDesktopFeed.Image = GetImage;
        

        } catch (Exception ex) {}
        }

        However, I do plan to take consideration in using a ScreenCaptureScreen() to relay this image to AForge video player to improve the over performance of the framerate since the PB update is too slow.

        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