473,326 Members | 2,196 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

BackgroundWorker "Cross-thread operation not valid..."

I'm using a BackgroundWorker to perform a file download from an ftp site.
Per good code design practices where I separate my UI code from my core
logic code (in this case my Download file method in my FileIO class) I've
established Public Event in my core logic classes along with RaiseEvents
(that will updated a progress bar on the UI side). This all works great
when I'm NOT using Threading (BackgroundWorker), however, as soon as I
introduce threading and fire off the download via a BackgroundWorker
control, I get the above error whenever I issue an RaiseEvents in my core
code.

I've gone thru the many samples and noticed that none of them separate UI
code from logic code (perhaps to save time for purpose of demonstration).
So it appears that the simple approach of using BackGroundWorker is once
again not very useful for anyone implementing more professional code
design/solutions.

It would appear to me that if I want this to work correctly, I'd have to
pass to my core logic the background worker control? Not an option. Or,
setup a public event for the BackgroundWorker control and change my raise
event to reference the event that will trigger the background worker?

I must admit, I'm not sure why this limitation exists?
Rob
Jun 18 '06 #1
5 14085
See here: http://weblogs.asp.net/justin_rogers...es/126345.aspx

Short answer, use InvokeRequired

"Rob R. Ainscough" <ro*****@pacbell.net> wrote in message
news:eU**************@TK2MSFTNGP04.phx.gbl...
I'm using a BackgroundWorker to perform a file download from an ftp site.
Per good code design practices where I separate my UI code from my core
logic code (in this case my Download file method in my FileIO class) I've
established Public Event in my core logic classes along with RaiseEvents
(that will updated a progress bar on the UI side). This all works great
when I'm NOT using Threading (BackgroundWorker), however, as soon as I
introduce threading and fire off the download via a BackgroundWorker
control, I get the above error whenever I issue an RaiseEvents in my core
code.

I've gone thru the many samples and noticed that none of them separate UI
code from logic code (perhaps to save time for purpose of demonstration).
So it appears that the simple approach of using BackGroundWorker is once
again not very useful for anyone implementing more professional code
design/solutions.

It would appear to me that if I want this to work correctly, I'd have to
pass to my core logic the background worker control? Not an option. Or,
setup a public event for the BackgroundWorker control and change my raise
event to reference the event that will trigger the background worker?

I must admit, I'm not sure why this limitation exists?
Rob

Jun 19 '06 #2
Brendan,

Good article, but it was written before .NET 2.0 was released. I'm using
the new BackgroundWork approach (in .NET 2.0) to threading as it implements
much cleaner and more manageable code than Invoke approach.

Still testing out some solutions, but I suspect I might be able to use
WithEvents on the BackgroudWorker defined in my class modules -- it also
appears that BackgroundWorker is part of system.componentmodel so I can
conceptually use it in my non-UI classes effectively retaining separation of
UI code.

Rob.

"Brendan Green" <bg****@nospam.nospam> wrote in message
news:Oh*************@TK2MSFTNGP04.phx.gbl...
See here: http://weblogs.asp.net/justin_rogers...es/126345.aspx

Short answer, use InvokeRequired

"Rob R. Ainscough" <ro*****@pacbell.net> wrote in message
news:eU**************@TK2MSFTNGP04.phx.gbl...
I'm using a BackgroundWorker to perform a file download from an ftp site.
Per good code design practices where I separate my UI code from my core
logic code (in this case my Download file method in my FileIO class) I've
established Public Event in my core logic classes along with RaiseEvents
(that will updated a progress bar on the UI side). This all works great
when I'm NOT using Threading (BackgroundWorker), however, as soon as I
introduce threading and fire off the download via a BackgroundWorker
control, I get the above error whenever I issue an RaiseEvents in my core
code.

I've gone thru the many samples and noticed that none of them separate UI
code from logic code (perhaps to save time for purpose of demonstration).
So it appears that the simple approach of using BackGroundWorker is once
again not very useful for anyone implementing more professional code
design/solutions.

It would appear to me that if I want this to work correctly, I'd have to
pass to my core logic the background worker control? Not an option. Or,
setup a public event for the BackgroundWorker control and change my raise
event to reference the event that will trigger the background worker?

I must admit, I'm not sure why this limitation exists?
Rob


Jun 19 '06 #3
Hi Rob,

You must use Control.Invoke to invoke code on the UI thread, which is the
thread that is running the message-loop, when you want to update the display
such as a progress bar. If you call a method on a Control from a different
Thread you will get an exception in the 2.0 framework.
Control.InvokeRequired is used to determine whether the code is calling from
another Thread, and if so Control.Invoke should be used. Control invocation
on the UI thread has nothing to do with the BackgroundWorker and is required
no matter the type of asynchronous architecture you implement.

// ctrl is assumed to be an instance of a Control or a derived Type

private void AsyncMethod()
{
if (ctrl.InvokeRequired)
{
ctrl.Invoke(new MethodInvoker(ctrl.Invalidate));
}
else
{
ctrl.Invalidate();
}
}

HTH

"Rob R. Ainscough" <ro*****@pacbell.net> wrote in message
news:eU**************@TK2MSFTNGP04.phx.gbl...
I'm using a BackgroundWorker to perform a file download from an ftp site.
Per good code design practices where I separate my UI code from my core
logic code (in this case my Download file method in my FileIO class) I've
established Public Event in my core logic classes along with RaiseEvents
(that will updated a progress bar on the UI side). This all works great
when I'm NOT using Threading (BackgroundWorker), however, as soon as I
introduce threading and fire off the download via a BackgroundWorker
control, I get the above error whenever I issue an RaiseEvents in my core
code.

I've gone thru the many samples and noticed that none of them separate UI
code from logic code (perhaps to save time for purpose of demonstration).
So it appears that the simple approach of using BackGroundWorker is once
again not very useful for anyone implementing more professional code
design/solutions.

It would appear to me that if I want this to work correctly, I'd have to
pass to my core logic the background worker control? Not an option. Or,
setup a public event for the BackgroundWorker control and change my raise
event to reference the event that will trigger the background worker?

I must admit, I'm not sure why this limitation exists?
Rob

Jun 19 '06 #4
Dave,

I've discovered that I can't access any controls from within the thread --
at first this tossed me for a loop (and I'm still not convinced this is a
good implementation by .NET 2.0 since the thread is still under the scope of
the calling source -- I'm using BackgroundWorker). However, I was
determine to keep my non-UI core classes (i.e. FileIO.Download) working for
any usage that might be tossed at it.

I was able to come up with a WithEvents and RaiseEvent approach in my non-UI
classes that would eventually make it to the UI handler which would call the
BackgroundWorker.ReportProgress. I created my own userState object class
(again non-UI) that could be used to provide any additional information to
the ProgressChanged.

In the core of the file download code I issue a raise event (using a ByRef
on boolean) after each byte stream is received that checks the state of the
BackgroundWorker.CancellationPending which is return in my local method's
boolean variable. I check to see if true and then exit and close the
stream, if not continues processing. So the class can handle both being
threaded and non-thread implementations.

Rob.
"Dave Sexton" <dave@jwa[remove.this]online.com> wrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
Hi Rob,

You must use Control.Invoke to invoke code on the UI thread, which is the
thread that is running the message-loop, when you want to update the
display such as a progress bar. If you call a method on a Control from a
different Thread you will get an exception in the 2.0 framework.
Control.InvokeRequired is used to determine whether the code is calling
from another Thread, and if so Control.Invoke should be used. Control
invocation on the UI thread has nothing to do with the BackgroundWorker
and is required no matter the type of asynchronous architecture you
implement.

// ctrl is assumed to be an instance of a Control or a derived Type

private void AsyncMethod()
{
if (ctrl.InvokeRequired)
{
ctrl.Invoke(new MethodInvoker(ctrl.Invalidate));
}
else
{
ctrl.Invalidate();
}
}

HTH

"Rob R. Ainscough" <ro*****@pacbell.net> wrote in message
news:eU**************@TK2MSFTNGP04.phx.gbl...
I'm using a BackgroundWorker to perform a file download from an ftp site.
Per good code design practices where I separate my UI code from my core
logic code (in this case my Download file method in my FileIO class) I've
established Public Event in my core logic classes along with RaiseEvents
(that will updated a progress bar on the UI side). This all works great
when I'm NOT using Threading (BackgroundWorker), however, as soon as I
introduce threading and fire off the download via a BackgroundWorker
control, I get the above error whenever I issue an RaiseEvents in my core
code.

I've gone thru the many samples and noticed that none of them separate UI
code from logic code (perhaps to save time for purpose of demonstration).
So it appears that the simple approach of using BackGroundWorker is once
again not very useful for anyone implementing more professional code
design/solutions.

It would appear to me that if I want this to work correctly, I'd have to
pass to my core logic the background worker control? Not an option. Or,
setup a public event for the BackgroundWorker control and change my raise
event to reference the event that will trigger the background worker?

I must admit, I'm not sure why this limitation exists?
Rob


Jun 19 '06 #5
Hmmm...

Here is some sample code that I'm using right now (uses
BackgroundWorkerThread and populates a listview for event logging):

BackgroundWorker m_eventWorker = new BackgroundWorker();

// This delegate enables asynchronous calls for adding items
// to a ListView control.
delegate void AddEventToListCallback(ListViewItem lvi);

....

public frmConsole()
{
InitializeComponent();
Helper.RunRemotingServices();

m_eventWorker.DoWork += new DoWorkEventHandler(m_eventWorker_DoWork);
}

private void frmConsole_Load(object sender, EventArgs e)
{
m_eventWorker.RunWorkerAsync();
}

void m_eventWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
if (Fenestra.Foundation.Core.EventQueue.Events.Count > 0)
{
Fenestra.Foundation.Core.Event et =
Fenestra.Foundation.Core.EventQueue.Events.Dequeue ();
ListViewItem i = new ListViewItem(new string[] {
et.Timestamp.ToString("dd/MM @ HH:mm:ss.mm"), et.Data });
i.Tag = et;

this.AddEventToList(i);
}

System.Threading.Thread.Sleep(new TimeSpan(0, 0, 5));
}
}
private void AddEventToList(ListViewItem lvi)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.lvEvents.InvokeRequired)
{
AddEventToListCallback d = new AddEventToListCallback(AddEventToList);
this.Invoke(d, new object[] { lvi });
}
else
{
this.lvEvents.Items.Add(lvi);
}
}

"Rob R. Ainscough" <ro*****@pacbell.net> wrote in message
news:eL**************@TK2MSFTNGP05.phx.gbl...
Brendan,

Good article, but it was written before .NET 2.0 was released. I'm using
the new BackgroundWork approach (in .NET 2.0) to threading as it
implements much cleaner and more manageable code than Invoke approach.

Still testing out some solutions, but I suspect I might be able to use
WithEvents on the BackgroudWorker defined in my class modules -- it also
appears that BackgroundWorker is part of system.componentmodel so I can
conceptually use it in my non-UI classes effectively retaining separation
of UI code.

Rob.

"Brendan Green" <bg****@nospam.nospam> wrote in message
news:Oh*************@TK2MSFTNGP04.phx.gbl...
See here: http://weblogs.asp.net/justin_rogers...es/126345.aspx

Short answer, use InvokeRequired

"Rob R. Ainscough" <ro*****@pacbell.net> wrote in message
news:eU**************@TK2MSFTNGP04.phx.gbl...
I'm using a BackgroundWorker to perform a file download from an ftp
site. Per good code design practices where I separate my UI code from my
core logic code (in this case my Download file method in my FileIO
class) I've established Public Event in my core logic classes along with
RaiseEvents (that will updated a progress bar on the UI side). This all
works great when I'm NOT using Threading (BackgroundWorker), however, as
soon as I introduce threading and fire off the download via a
BackgroundWorker control, I get the above error whenever I issue an
RaiseEvents in my core code.

I've gone thru the many samples and noticed that none of them separate
UI code from logic code (perhaps to save time for purpose of
demonstration). So it appears that the simple approach of using
BackGroundWorker is once again not very useful for anyone implementing
more professional code design/solutions.

It would appear to me that if I want this to work correctly, I'd have to
pass to my core logic the background worker control? Not an option.
Or, setup a public event for the BackgroundWorker control and change my
raise event to reference the event that will trigger the background
worker?

I must admit, I'm not sure why this limitation exists?
Rob



Jun 19 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: dmartin_1 | last post by:
I'm building an application with Visual Basic 2005. The application is multi threaded. It has a record counter on the form that counts up to completion. It works fine throughout the process as...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.