Access to class member variables inside the BackgroundWorker DoWork event handler and other BackgroundWorker constraints

Question 1

In the DoWork event handler for BackgroundWorker, is it safe to access (read and write) the member variables of the class containing BackgroundWorker? Is it safe to access other variables that are not declared inside the DoWork event handler itself?

Obviously, DoWork should not access any user interface objects, say, a WinForms application, since the user interface should only be updated from the user interface stream. But what about accessing other (non-UI) member variables?

The reason I ask is because I saw a random comment when Googling says that access to member variables is not allowed. The only example I can find at the moment is a comment on this MSDN page that says:

Note that BGW can throw exceptions if it tries to access or change class level variables. All data must be transmitted to him by delegates and events.

And:

NEVER. NEVER. Never try to reference variables that are not declared inside DoWork. It seems to work from time to time, but in fact you are just lucky.

As far as I know, MSDN itself does not document any restrictions of this kind (although if I am mistaken, I would appreciate the link). But such comments seem to appear from time to time.

(Of course, if DoWork accesses / changes a member variable that can be accessed / changed at the same time, you need to synchronize access to this field, for example, using a lock object. Quotes seem to require a complete ban on access to member variables , not just sync access!)

Question 2

To make this a more general question, are there any other (not documented?) Restrictions that BackgroundWorker users should be aware of beyond the above? Any "best practices" perhaps?

+1
source share
3 answers

The comments in question 1 are incorrect. From the CLR point of view, this is normal for accessing form class members from BackgroundWorker (except, as you say, for controls because they have thread similarity, but access to non-Control elements like integers is great) . Yes, as you noticed, if you do this, then you need to synchronize access correctly: it is always in a multithreading script. But poor synchronization will not throw an exception, as the first commenter suggests: it just leads to good damage to old data (which is much better, of course!). And it’s not true to say that you are “just lucky.” This is not fate; it is a matter of good synchronization.

Why can I qualify this remark with a “CLR perspective”? Firstly, because multi-threaded access to the state is difficult. Therefore, although this is not problematic for the CLR, it can be problematic for the person programming the CLR. Secondly, because if your form class contains many non-UI materials that BackgroundWorker requires, this may indicate a poorly structured application. This may mean that this material should be packed into an object, and BackgroundWorker should call a method on this object, and not iterate over the state of the Form object.

+1
source

If the variable is a member of the event, everything is fine.

If the variable is a member, let's talk about the form with which this BackgroundWorker is confused, I think you should lock it before reading or writing a value for it, even for primitive types such as integers, booleans, strings, etc. .

Remember that .NET 3.5 collections are not threaded.

Please pay attention to this link , as it expresses some other points of view and related links to a topic of interest to you.

0
source

Like most things, it depends. I believe the commentator wrote these warnings because these are common problem areas. Following this advice, you have a long way to go to prevent trouble, but it also unnecessarily limits. If you understand why using member variables often leads to problems with BackgroundWorker , you can determine if your application affects and how best to resolve problems.

Inside DoWork access to member variables (also known as fields) comes from a workflow. The first problem is that the member variable is updated to refer to zero or another object on some thread after the background worker has started. If possible, synchronization (the synclock keyword in C # or another mechanism) is appropriate. The second problem is that although the link may be stable, the object itself may be an unsafe thread. If the class is part of the .NET Framework, the documentation for the class almost always explains whether it is thread safe. If this is unsafe, adding synchronization to both access the member variable that references the object and the use of the object itself often allows this.

You should especially look for member variables that reference Windows Forms GUI objects (for example, controls). Although these links are usually stable, as a rule, these objects are not thread safe. Worse, synclock will not solve the problem because Windows Forms objects have a special requirement that calls to these objects must be made in the GUI thread that was originally associated with the objects. To call these objects, you can use the Invoke or BeginInvoke object (defined in the Control class) to force the code to run in the GUI thread for the object. Alternatively, GUI updates can be placed in the ProgressChanged and RunWorkerCompleted BackgroundWorker events: unlike DoWork , these events occur in the GUI thread.

Multithreading is known to be full of pitfalls. BackgroundWorker helps simplify some things, but many of the traps remain. I hope you understand that a solid understanding of multi-disciplinary programming is important for integrating BackgroundWorker into applications.

0
source

Source: https://habr.com/ru/post/1304769/


All Articles