Threading problem

C

Chris Saunders

I'm using System.ComponentModel.BackgroundWorker to do some drawing in my
application.
The thread seems to run fine but it runs twice and I can't see why.
I'm going to show my code with everything that I think is not relevant
removed.
Perhaps the drawBitmap function can be ignored, I just included it because
it is the
actual work the tread is performing. (It's just a test case.)
Can anyone help?

namespace Mandolin
{
public partial class MainForm : Form
{

public MainForm()
{
backgroundWorkerDraw.DoWork += new
DoWorkEventHandler(backgroundWorkerDraw_DoWork);
backgroundWorkerDraw.ProgressChanged += new
ProgressChangedEventHandler(backgroundWorkerDraw_ProgressChanged);
backgroundWorkerDraw.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(backgroundWorkerDraw_RunWorkerCompleted);
}

private void goToolStripMenuItem_Click(object sender, EventArgs e)
{
if (backgroundWorkerDraw.IsBusy == false)
{
backgroundWorkerDraw.RunWorkerAsync();
}
}

private void drawBitmap(BackgroundWorker worker, DoWorkEventArgs e)
{
if (worker.CancellationPending)
e.Cancel = true;
else
{
for (int r = startRow; r < bitmapHeight; r++)
{
if (worker.CancellationPending)
e.Cancel = true;
else
{
for (int c = 0; c < bitmapWidth; c++)
{
mutex.WaitOne();
bitmap.SetPixel(c, r, Color.FromArgb(r * c));
mutex.ReleaseMutex();
if (e.Cancel)
c = bitmapWidth;
}
}
worker.ReportProgress((int)(((double)r /
(double)bitmapHeight) * 100));
if (e.Cancel)
{
mutex.WaitOne();
if (pauseButtonPushed == true)
startRow = r;
if (stopButtonPushed == true)
startRow = 0;
r = bitmapHeight;
mutex.ReleaseMutex();
}
}
}
}

private void backgroundWorkerDraw_DoWork(object sender,
DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
drawBitmap(worker, e);
}

private void backgroundWorkerDraw_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
statusBar.Text = e.ProgressPercentage.ToString() + " percent
complete.";
Graphics g = CreateGraphics();
mutex.WaitOne();
g.DrawImage(bitmap, rect);
mutex.ReleaseMutex();
}

private void backgroundWorkerDraw_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
toolStripButtonPlay.Enabled = true;
toolStripButtonPause.Enabled = false;
toolStripButtonStop.Enabled = false;
goToolStripMenuItem.Enabled = true;
pauseToolStripMenuItem.Enabled = false;
stopToolStripMenuItem.Enabled = false;
statusBar.Text = statusBarReady;
}
}
}

Regards
Chris Saunders
 
A

Alvin Bruney

Chris,
What I don't get is why this call isn't failing. Backgroundworker appears to
be touching a windows resource (a quick eyeball of the code)

--

________________________
Warm regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
Professional VSTO.NET - Wrox/Wiley
The O.W.C. Black Book with .NET
www.lulu.com/owc, Amazon
Blog: http://www.msmvps.com/blogs/alvin
-------------------------------------------------------
 
C

Chris Saunders

Ah, a response!!! I'm just learning about using multithreading in C#.
Actually fairly new to C#. I can assure you that this code is performing
with no apparent problems. The only problem that I know of is that
the thread runs twice before it stops. I'm not sure what you are referring
to as regards "touching a windows resource" but I attempted to use
methods I found in the MSDN documentation for updating the UI
controls.

If you are knowledgeable in this area I would much appreciate a closer
look at the code. I know it is a bit much but I tried to minimize as best
I could without missing anything relevant. I'm not even sure if my
approach to this is sensible.

Regards
Chris Saunders

Alvin Bruney said:
Chris,
What I don't get is why this call isn't failing. Backgroundworker appears
to be touching a windows resource (a quick eyeball of the code)

--

________________________
Warm regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
Professional VSTO.NET - Wrox/Wiley
The O.W.C. Black Book with .NET
www.lulu.com/owc, Amazon
Blog: http://www.msmvps.com/blogs/alvin
-------------------------------------------------------

Chris Saunders said:
I'm using System.ComponentModel.BackgroundWorker to do some drawing in my
application.
The thread seems to run fine but it runs twice and I can't see why.
I'm going to show my code with everything that I think is not relevant
removed.
Perhaps the drawBitmap function can be ignored, I just included it
because it is the
actual work the tread is performing. (It's just a test case.)
Can anyone help?

namespace Mandolin
{
public partial class MainForm : Form
{

public MainForm()
{
backgroundWorkerDraw.DoWork += new
DoWorkEventHandler(backgroundWorkerDraw_DoWork);
backgroundWorkerDraw.ProgressChanged += new
ProgressChangedEventHandler(backgroundWorkerDraw_ProgressChanged);
backgroundWorkerDraw.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(backgroundWorkerDraw_RunWorkerCompleted);
}

private void goToolStripMenuItem_Click(object sender, EventArgs e)
{
if (backgroundWorkerDraw.IsBusy == false)
{
backgroundWorkerDraw.RunWorkerAsync();
}
}

private void drawBitmap(BackgroundWorker worker, DoWorkEventArgs
e)
{
if (worker.CancellationPending)
e.Cancel = true;
else
{
for (int r = startRow; r < bitmapHeight; r++)
{
if (worker.CancellationPending)
e.Cancel = true;
else
{
for (int c = 0; c < bitmapWidth; c++)
{
mutex.WaitOne();
bitmap.SetPixel(c, r, Color.FromArgb(r * c));
mutex.ReleaseMutex();
if (e.Cancel)
c = bitmapWidth;
}
}
worker.ReportProgress((int)(((double)r /
(double)bitmapHeight) * 100));
if (e.Cancel)
{
mutex.WaitOne();
if (pauseButtonPushed == true)
startRow = r;
if (stopButtonPushed == true)
startRow = 0;
r = bitmapHeight;
mutex.ReleaseMutex();
}
}
}
}

private void backgroundWorkerDraw_DoWork(object sender,
DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
drawBitmap(worker, e);
}

private void backgroundWorkerDraw_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
statusBar.Text = e.ProgressPercentage.ToString() + " percent
complete.";
Graphics g = CreateGraphics();
mutex.WaitOne();
g.DrawImage(bitmap, rect);
mutex.ReleaseMutex();
}

private void backgroundWorkerDraw_RunWorkerCompleted(object
sender, RunWorkerCompletedEventArgs e)
{
toolStripButtonPlay.Enabled = true;
toolStripButtonPause.Enabled = false;
toolStripButtonStop.Enabled = false;
goToolStripMenuItem.Enabled = true;
pauseToolStripMenuItem.Enabled = false;
stopToolStripMenuItem.Enabled = false;
statusBar.Text = statusBarReady;
}
}
}

Regards
Chris Saunders
 
A

Alvin Bruney

I tried to run your project but it doesn't compile under 2.0. You need to
produce a short but complete program that demonstrates the problem. See this
definition for what a short but complete program is:
http://www.yoda.arachsys.com/csharp/complete.html

Basically, I or anyone else should be able to copy your code into a project
and run it successfully and see the problem. Newsgroupies don't particularly
like copying code and spending a day figuring out what variables are and how
to hack the program to get it to compile successfully.

--

________________________
Warm regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
Professional VSTO.NET - Wrox/Wiley
The O.W.C. Black Book with .NET
www.lulu.com/owc, Amazon
Blog: http://www.msmvps.com/blogs/alvin
-------------------------------------------------------

Chris Saunders said:
Ah, a response!!! I'm just learning about using multithreading in C#.
Actually fairly new to C#. I can assure you that this code is performing
with no apparent problems. The only problem that I know of is that
the thread runs twice before it stops. I'm not sure what you are
referring
to as regards "touching a windows resource" but I attempted to use
methods I found in the MSDN documentation for updating the UI
controls.

If you are knowledgeable in this area I would much appreciate a closer
look at the code. I know it is a bit much but I tried to minimize as best
I could without missing anything relevant. I'm not even sure if my
approach to this is sensible.

Regards
Chris Saunders

Alvin Bruney said:
Chris,
What I don't get is why this call isn't failing. Backgroundworker appears
to be touching a windows resource (a quick eyeball of the code)

--

________________________
Warm regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
Professional VSTO.NET - Wrox/Wiley
The O.W.C. Black Book with .NET
www.lulu.com/owc, Amazon
Blog: http://www.msmvps.com/blogs/alvin
-------------------------------------------------------

Chris Saunders said:
I'm using System.ComponentModel.BackgroundWorker to do some drawing in
my application.
The thread seems to run fine but it runs twice and I can't see why.
I'm going to show my code with everything that I think is not relevant
removed.
Perhaps the drawBitmap function can be ignored, I just included it
because it is the
actual work the tread is performing. (It's just a test case.)
Can anyone help?

namespace Mandolin
{
public partial class MainForm : Form
{

public MainForm()
{
backgroundWorkerDraw.DoWork += new
DoWorkEventHandler(backgroundWorkerDraw_DoWork);
backgroundWorkerDraw.ProgressChanged += new
ProgressChangedEventHandler(backgroundWorkerDraw_ProgressChanged);
backgroundWorkerDraw.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(backgroundWorkerDraw_RunWorkerCompleted);
}

private void goToolStripMenuItem_Click(object sender, EventArgs
e)
{
if (backgroundWorkerDraw.IsBusy == false)
{
backgroundWorkerDraw.RunWorkerAsync();
}
}

private void drawBitmap(BackgroundWorker worker, DoWorkEventArgs
e)
{
if (worker.CancellationPending)
e.Cancel = true;
else
{
for (int r = startRow; r < bitmapHeight; r++)
{
if (worker.CancellationPending)
e.Cancel = true;
else
{
for (int c = 0; c < bitmapWidth; c++)
{
mutex.WaitOne();
bitmap.SetPixel(c, r, Color.FromArgb(r * c));
mutex.ReleaseMutex();
if (e.Cancel)
c = bitmapWidth;
}
}
worker.ReportProgress((int)(((double)r /
(double)bitmapHeight) * 100));
if (e.Cancel)
{
mutex.WaitOne();
if (pauseButtonPushed == true)
startRow = r;
if (stopButtonPushed == true)
startRow = 0;
r = bitmapHeight;
mutex.ReleaseMutex();
}
}
}
}

private void backgroundWorkerDraw_DoWork(object sender,
DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
drawBitmap(worker, e);
}

private void backgroundWorkerDraw_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
statusBar.Text = e.ProgressPercentage.ToString() + " percent
complete.";
Graphics g = CreateGraphics();
mutex.WaitOne();
g.DrawImage(bitmap, rect);
mutex.ReleaseMutex();
}

private void backgroundWorkerDraw_RunWorkerCompleted(object
sender, RunWorkerCompletedEventArgs e)
{
toolStripButtonPlay.Enabled = true;
toolStripButtonPause.Enabled = false;
toolStripButtonStop.Enabled = false;
goToolStripMenuItem.Enabled = true;
pauseToolStripMenuItem.Enabled = false;
stopToolStripMenuItem.Enabled = false;
statusBar.Text = statusBarReady;
}
}
}

Regards
Chris Saunders
 
C

Chris Saunders

OK, thanks Alvin. I didn't intend this code to be buildable as I was
attempting to keep
it as short as possible and thought that even what I came up with was too
long for
anyone to bother with.

This will take me a little time but I will attemt to provide something
appropriate
as soon as I can. I don't think I can follow all of the guidelines from the
link
you gave - I'll do my best.

I've been looking at this code for a couple of weeks now and just cannot see
the
problem = it's probably something extremely stupid.

I appreciate your assistance.

Regards
Chris Saunders

Alvin Bruney said:
I tried to run your project but it doesn't compile under 2.0. You need to
produce a short but complete program that demonstrates the problem. See
this definition for what a short but complete program is:
http://www.yoda.arachsys.com/csharp/complete.html

Basically, I or anyone else should be able to copy your code into a
project and run it successfully and see the problem. Newsgroupies don't
particularly like copying code and spending a day figuring out what
variables are and how to hack the program to get it to compile
successfully.

--

________________________
Warm regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
Professional VSTO.NET - Wrox/Wiley
The O.W.C. Black Book with .NET
www.lulu.com/owc, Amazon
Blog: http://www.msmvps.com/blogs/alvin
-------------------------------------------------------

Chris Saunders said:
Ah, a response!!! I'm just learning about using multithreading in C#.
Actually fairly new to C#. I can assure you that this code is performing
with no apparent problems. The only problem that I know of is that
the thread runs twice before it stops. I'm not sure what you are
referring
to as regards "touching a windows resource" but I attempted to use
methods I found in the MSDN documentation for updating the UI
controls.

If you are knowledgeable in this area I would much appreciate a closer
look at the code. I know it is a bit much but I tried to minimize as
best
I could without missing anything relevant. I'm not even sure if my
approach to this is sensible.

Regards
Chris Saunders

Alvin Bruney said:
Chris,
What I don't get is why this call isn't failing. Backgroundworker
appears to be touching a windows resource (a quick eyeball of the code)

--

________________________
Warm regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
Professional VSTO.NET - Wrox/Wiley
The O.W.C. Black Book with .NET
www.lulu.com/owc, Amazon
Blog: http://www.msmvps.com/blogs/alvin
-------------------------------------------------------

I'm using System.ComponentModel.BackgroundWorker to do some drawing in
my application.
The thread seems to run fine but it runs twice and I can't see why.
I'm going to show my code with everything that I think is not relevant
removed.
Perhaps the drawBitmap function can be ignored, I just included it
because it is the
actual work the tread is performing. (It's just a test case.)
Can anyone help?

namespace Mandolin
{
public partial class MainForm : Form
{

public MainForm()
{
backgroundWorkerDraw.DoWork += new
DoWorkEventHandler(backgroundWorkerDraw_DoWork);
backgroundWorkerDraw.ProgressChanged += new
ProgressChangedEventHandler(backgroundWorkerDraw_ProgressChanged);
backgroundWorkerDraw.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(backgroundWorkerDraw_RunWorkerCompleted);
}

private void goToolStripMenuItem_Click(object sender, EventArgs
e)
{
if (backgroundWorkerDraw.IsBusy == false)
{
backgroundWorkerDraw.RunWorkerAsync();
}
}

private void drawBitmap(BackgroundWorker worker, DoWorkEventArgs
e)
{
if (worker.CancellationPending)
e.Cancel = true;
else
{
for (int r = startRow; r < bitmapHeight; r++)
{
if (worker.CancellationPending)
e.Cancel = true;
else
{
for (int c = 0; c < bitmapWidth; c++)
{
mutex.WaitOne();
bitmap.SetPixel(c, r, Color.FromArgb(r *
c));
mutex.ReleaseMutex();
if (e.Cancel)
c = bitmapWidth;
}
}
worker.ReportProgress((int)(((double)r /
(double)bitmapHeight) * 100));
if (e.Cancel)
{
mutex.WaitOne();
if (pauseButtonPushed == true)
startRow = r;
if (stopButtonPushed == true)
startRow = 0;
r = bitmapHeight;
mutex.ReleaseMutex();
}
}
}
}

private void backgroundWorkerDraw_DoWork(object sender,
DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
drawBitmap(worker, e);
}

private void backgroundWorkerDraw_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
statusBar.Text = e.ProgressPercentage.ToString() + " percent
complete.";
Graphics g = CreateGraphics();
mutex.WaitOne();
g.DrawImage(bitmap, rect);
mutex.ReleaseMutex();
}

private void backgroundWorkerDraw_RunWorkerCompleted(object
sender, RunWorkerCompletedEventArgs e)
{
toolStripButtonPlay.Enabled = true;
toolStripButtonPause.Enabled = false;
toolStripButtonStop.Enabled = false;
goToolStripMenuItem.Enabled = true;
pauseToolStripMenuItem.Enabled = false;
stopToolStripMenuItem.Enabled = false;
statusBar.Text = statusBarReady;
}
}
}

Regards
Chris Saunders
 
C

Chris Saunders

I attempted what you suggested and in my reduced application this problem
does not occur. This gives me some hints. I'll work on this some more and
post again if necessary.

Thanks again Alvin.

Regards
Chris Saunders

Alvin Bruney said:
I tried to run your project but it doesn't compile under 2.0. You need to
produce a short but complete program that demonstrates the problem. See
this definition for what a short but complete program is:
http://www.yoda.arachsys.com/csharp/complete.html

Basically, I or anyone else should be able to copy your code into a
project and run it successfully and see the problem. Newsgroupies don't
particularly like copying code and spending a day figuring out what
variables are and how to hack the program to get it to compile
successfully.

--

________________________
Warm regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
Professional VSTO.NET - Wrox/Wiley
The O.W.C. Black Book with .NET
www.lulu.com/owc, Amazon
Blog: http://www.msmvps.com/blogs/alvin
-------------------------------------------------------

Chris Saunders said:
Ah, a response!!! I'm just learning about using multithreading in C#.
Actually fairly new to C#. I can assure you that this code is performing
with no apparent problems. The only problem that I know of is that
the thread runs twice before it stops. I'm not sure what you are
referring
to as regards "touching a windows resource" but I attempted to use
methods I found in the MSDN documentation for updating the UI
controls.

If you are knowledgeable in this area I would much appreciate a closer
look at the code. I know it is a bit much but I tried to minimize as
best
I could without missing anything relevant. I'm not even sure if my
approach to this is sensible.

Regards
Chris Saunders

Alvin Bruney said:
Chris,
What I don't get is why this call isn't failing. Backgroundworker
appears to be touching a windows resource (a quick eyeball of the code)

--

________________________
Warm regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
Professional VSTO.NET - Wrox/Wiley
The O.W.C. Black Book with .NET
www.lulu.com/owc, Amazon
Blog: http://www.msmvps.com/blogs/alvin
-------------------------------------------------------

I'm using System.ComponentModel.BackgroundWorker to do some drawing in
my application.
The thread seems to run fine but it runs twice and I can't see why.
I'm going to show my code with everything that I think is not relevant
removed.
Perhaps the drawBitmap function can be ignored, I just included it
because it is the
actual work the tread is performing. (It's just a test case.)
Can anyone help?

namespace Mandolin
{
public partial class MainForm : Form
{

public MainForm()
{
backgroundWorkerDraw.DoWork += new
DoWorkEventHandler(backgroundWorkerDraw_DoWork);
backgroundWorkerDraw.ProgressChanged += new
ProgressChangedEventHandler(backgroundWorkerDraw_ProgressChanged);
backgroundWorkerDraw.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(backgroundWorkerDraw_RunWorkerCompleted);
}

private void goToolStripMenuItem_Click(object sender, EventArgs
e)
{
if (backgroundWorkerDraw.IsBusy == false)
{
backgroundWorkerDraw.RunWorkerAsync();
}
}

private void drawBitmap(BackgroundWorker worker, DoWorkEventArgs
e)
{
if (worker.CancellationPending)
e.Cancel = true;
else
{
for (int r = startRow; r < bitmapHeight; r++)
{
if (worker.CancellationPending)
e.Cancel = true;
else
{
for (int c = 0; c < bitmapWidth; c++)
{
mutex.WaitOne();
bitmap.SetPixel(c, r, Color.FromArgb(r *
c));
mutex.ReleaseMutex();
if (e.Cancel)
c = bitmapWidth;
}
}
worker.ReportProgress((int)(((double)r /
(double)bitmapHeight) * 100));
if (e.Cancel)
{
mutex.WaitOne();
if (pauseButtonPushed == true)
startRow = r;
if (stopButtonPushed == true)
startRow = 0;
r = bitmapHeight;
mutex.ReleaseMutex();
}
}
}
}

private void backgroundWorkerDraw_DoWork(object sender,
DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
drawBitmap(worker, e);
}

private void backgroundWorkerDraw_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
statusBar.Text = e.ProgressPercentage.ToString() + " percent
complete.";
Graphics g = CreateGraphics();
mutex.WaitOne();
g.DrawImage(bitmap, rect);
mutex.ReleaseMutex();
}

private void backgroundWorkerDraw_RunWorkerCompleted(object
sender, RunWorkerCompletedEventArgs e)
{
toolStripButtonPlay.Enabled = true;
toolStripButtonPause.Enabled = false;
toolStripButtonStop.Enabled = false;
goToolStripMenuItem.Enabled = true;
pauseToolStripMenuItem.Enabled = false;
stopToolStripMenuItem.Enabled = false;
statusBar.Text = statusBarReady;
}
}
}

Regards
Chris Saunders
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top