The problem is that your worker thread is attempting to access a UI element which is not allowed. The exception you are getting is warning you about this. Often times you do not even get that. Instead your application will fail unpredictably and spectacularly.
You could use Control.Invoke
to marshal the execution of a delegate onto the UI thread. This delegate would perform the lbPrimes.Items.Add
operations. However, I do not recommend this approach in this case. The reason is because it will slow down the worker thread.
My preferred solution would be to have the worker thread add currval
to a ConcurrentQueue
. Then the UI thread will periodically poll this collection via a System.Windows.Forms.Timer
to dequeue the values and place them in the ListBox
. This has a lot of advantages over using Control.Invoke
.
- It removes the tight coupling between the worker and UI threads that
Invoke
imposes.
- It puts the responsibility of updating the UI in the UI thread where it should belong anyway.
- The UI thread gets to dictate when and how often the update takes place.
- The worker thread does not have to wait for the UI to respond to the
Invoke
request. It will increase the throughput on the worker thread.
- It is more efficient since
Invoke
is costly operation.
- Many of the subtle race conditions that arise when attempting to a terminate a worker thread using
Invoke
naturally go away.
Here is how my preferred option might look.
private void calculate()
{
int currval = 2;
int devide = 2;
while (!interrupt)
{
for (int i = 2; i < currval/2; i++)
{
if (2 % i != 0)
{
queue.Add(currval); // ConcurrentQueue
}
}
currval++;
}
}
private void Timer_Tick(object sender, EventArgs args)
{
int value;
while (queue.TryDequeue(out value))
{
lbPrimes.Items.Add(value.ToString());
}
}
I noticed a couple of other problems.
Thread.Interrupt
unblocks the BCL waiting calls like WaitOne
, Join
, Sleep
, etc. Your usage of it serves no purpose. I think what you want to do instead is set interrupt = true
.
- You should probably
interrupt
in the for
loop instead of the while
loop. If currval
gets big enough it will take longer and longer for the thread to respond to the interrupt request.