I have a class that inherits from BackgroundWorker to do some specific stuff on a remote server. I've added properties for this class to store information needed for the job to complete. Example:
public class GenerateFileWorker : System.ComponentModel.BackgroundWorker
{
public string LocalFileName { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public GenerateFileWorker() {}
public GenerateFileWorker(string username, string password, string localFileName)
{
Username = username;
Password = password;
LocalFileName = localFileName;
}
protected override void OnDoWork(DoWorkEventArgs e) {
// ...
}
I know lock is needed to safely access objects outside the class, but what about within? Do I need it when accessing the properties of the current instance within OnDoWork()?
It's not a question of what class you're inheriting from. It's a question of whether multiple threads may concurrently read or modify properties or fields so that they interfere with each other, or one thread reads while another is in the middle of updating something. That's when you would need a lock (or some other mechanism) to ensure that such conflicts don't occur. (That's an oversimplification for brevity.)
From the documentation:
The BackgroundWorker class allows you to run an operation on a separate, dedicated thread.
The idea is that the UI thread only interacts with the background thread by canceling it, getting progress reports from it, or being notified that it has finished or failed. It doesn't directly access the variables (state) used within the process.
One thing in your class that stands out is this:
public string LocalFileName { get; set; }
public string Username { get; set; }
public string Password { get; set; }
Because those are read/write properties it's possible that the UI thread could update them while the background thread is using them. I imagine that's probably not your intent. Do those properties need to be writable? Or do they even need to be properties at all? (If they don't need to be properties, do you need to inherit?)
Perhaps you can initialize variables containing those values at the beginning of the background process. Now those variables are private within the method executed by the background process, which means that it's not possible for the UI thread or any other thread to interact with them.
Related
I am working on a WPF Application that was running smooth until I added threadding. I wanted to ease the saving/autosaving process by putting it into a BackgroundWorker so my UI is not blocked while saving occours.
Think of my App as a custom photobook maker.
Lets assume my UI consists of several Image Objects. The Source for those images lies within a custom PhotobookImageObject because each selected Image also contains additional Metadata.
PhotobookImageObject
public class PhotobookImageObject
{
public BitmapSource source { get; set; }
public String unimportantMetadata{ get; set; }
}
When I want to save, I want to save the complete Photobook. For simplicity:
Photobook
public class Photobook: INotifyPropertyChanged
{
public List<PhotobookImageObject> Photos{ get; set;}
public String otherMetaData { get; set;}
}
My Saving process worked when not using Threads. But ever since Im running it in a BackgroundWorker I can not access the PhotobookImageObjects in the list anymore.
Now I know the Thread for Saving can not Acces Objects from different Threads. This is why I am using a custom Class to Push the object into the thread of the BackgroundWorker. I found this solution here: How do you pass a List<> of Lists<> to a background worker?
Here is the acutal code:
Setting up the Worker:
private static BackgroundWorker saveWorker = new BackgroundWorker();
private static void saveWorkerExec(Photobook book, String Location, bool notAuto)
{
saveWorker.DoWork += doWork;
saveWorker.WorkerSupportsCancellation = true;
saveWorker.RunWorkerCompleted += (s, o) =>
{
Helper.Message("Photobook saved");
if (o.Error != null)
{
MessageBox.Show("There was an error while saving! \n\n" + o.Error.ToString());
}
};
BGObj obj = new BGObj
{
bk = book,
Loc = Location,
not = notAuto
};
saveWorker.RunWorkerAsync(obj);
}
The custom class I use to transfer the Data:
public class BGObj
{
public Photobook bk { get; set; }
public String Loc { get; set; }
public bool not { get; set; }
}
And the actual part where the BackgroundWorker should receive the class into his own Thread:
private static void doWork(object sender, DoWorkEventArgs e)
{
BGObj received = e.Argument as BGObj;
Photobook book= received.bk;
String Location = received.Loc;
bool notAuto = received.not;
//this function can not Access the books.Photos.last().source for example.
SaveProjectToContainer(book, Location, notAuto);
}
I am still receiving a System.InvalidOperationException when I try to access the BitmapSource of the PhotobookImageObject in the Photos List in Photobook.
My assumption: the BGobj I am creating is only referencing the actual Photobook so the data of its members is still resting in the wrong thread. How on earth can I make sure all submembers of my objects are actually passed to the Thread where I want to process them? Or am I wrong here and its something else?
Thank you for your time.
Since nobody could help me with the issue I followed Theodors approach and switched to a more modern approach using Async/Await.
From my understanding this is not making the actions run in the background but still freeing the UI thread and running the await" tasks "inbetween" when the thread has capacity free. This allows me to access the UI-elements and still stop the application from freezin a bit while autosaving.
If someone needs a few hints how to solve this think of it like this:
public static void NotMain()
{
// queue following function. void Main for example would continue running after this.
await do_stuff_in_between(var object);
// Stuff after await will only happen if the function is done but UI is not blocked
Console.WriteLine("saving done");
}
public static async Task do_stuff_in_between(var object)
{
// do stuff with object or whatever you want.
}
I'm multithreading a real-time game, and would like to prevent the state variables of objects on one thread from being set from another thread. This will make preventing race conditions a lot easier.
I would still like to be able to read the state of other objects, however. I'm intending to use a double buffer system, where one state object is used as the forebuffer and makes state changes while the other is used as the backbuffer and provides the (previous frame's) state to other objects. I need to be able to read state information from the backbuffer to make changes in the forebuffer.
The issue is that even if the variables setter is private, it's possible to change it from another object of the same class.
public class State
{
//Some example state information
public string StateVar1 { get; private set; }
//This method will be farmed out to multiple other threads
public void Update(State aDifferentStateObject)
{
StateVar1 = "I want to be able to do this";
string infoFromAnotherObject = aDifferentStateObject.StateVar1; //I also want to be able to do this
aDifferentStateObject.StateVar1 = "I don't want to be able to do this, but I can";
}
}
May not be the most direct solution, but one way to protect the properties is to use an interface.
public interface IState
{
string StateVar1 { get; }
}
public class State:IState
{
//Some example state information
public string StateVar1 { get; private set; }
//This method will be farmed out to multiple other threads
public void Update(IState aDifferentStateObject)
{
StateVar1 = "I want to be able to do this"; // Allowed
string infoFromAnotherObject = aDifferentStateObject.StateVar1;
aDifferentStateObject.StateVar1 = "I don't want to be able to do this, but I can"; // NOT allowed
}
}
If you're writing a class, it's assumed that you'll make the class work the way you want it to work. The purpose of making stuff private is to prevent your co-workers (or clients) from breaking your class's concerns while they work on their own classes/functions/modules.
Saying "I don't want to be able to do this thing." is somewhat missing the point.
That said, the thing that's nice about less permissive languages in general is that they prevent your co-workers from writing crappy or non-idiomatic code. The other answers show idioms you could use that would make it harder for your peers to later edit break your nice elegant pattern. Anu Viswan's get's my vote.
add field this0=this and in the setter, check that this==this0.
it's possible to change it from another object of the same class.
You cannot stop your own class from setting private setters.
I mean after all, you are the author of that class, its only your fingers you have to worry about.
public class SomeOtherNonRelatedClass
{
public void Update(State aDifferentStateObject)
{
// the world is as it should be
aDifferentStateObject.StateVar1 = "bang!!!" // compiler error
}
}
If you would like to prevent your self from changing your own member, then use an extension method
public class Extensions
{
public void Update(this State aDifferentStateObject)
{
// the world is as it should be
aDifferentStateObject.StateVar1 = "bang!!!" // compiler error
}
}
or make it truly read only (though is probably not useful)
public string StateVar1 { get; }
or a backing field, so you can set it internally
private string backingField;
public string StateVar1
{
get => backingField;
}
I am trying to synchronise changes to a DataContract between my service and it's consumers. I am having trouble designing a maintainable way of informing of property changes.
For example, I want to keep the below synchronised:
[DataContract]
public class MyObject
{
[DataMember]
public Guid Id { get; private set; } = Guid.NewGuid();
[DataMember]
public int Foo { get; set; }
[DataMember]
public string Bar { get; set; }
}
My original approach was to use an event which took a property name and an object, as such:
public delegate void PropertyChangedEventHandler(Guid id, string propertyName, object value);
The service & consumers could then subscribe to the property changes:
myObject.PropertyChanged += MyObjectPropertyChanged;
// MyObject would raise the property change inside of the property set.
private void MyObjectPropertyChanged(Guid id, string propertyName, object value)
{
// Depending on which end is listening the service can send
// the change to the consumer or vica versa
}
I have encountered an issue using this method as the serializer could not determine how to serialize object.
I now don't know how to handle informing of changes. I can see two approaches but I am hoping for a better solution.
I could inform the consumer/service that a change has been made. It can then request from the service/consumer for the changed MyObject. I see this being a problem if more than one consumer changes the same object at the same time (as the service is concurrency is set to multiple). It could result in one consumer's changes being lost.
The second approach is to create an EventArgs, which mirrors the properties of the MyObject and you access the property based on the property name passed with the EventArgs and synchronise the local copy. This would allow two consumers to change different properties without fear of either being lost. However this feels like a lot of repeated code. A lot of unused data is also passed around as MyObject grows. Admitidly there is room for reflection in regards to reading and setting the appropriate property.
For example:
public class MyObjectPropertyChangedEventArgs : EventArgs
{
public Guid Id { get; set; }
public string PropertyName { get; set; }
// Then one of the relative property below would be set to the new value
public int Foo { get; set; }
public string Bar { get; set; }
}
I don't see this being an uncommon use case and was hoping for some insight into how this is usually done?
As far as service is concerned, why do not you leverage of CallbackContract in order to notify client that some changes occured?
On client side in turn DataContract can implement INotifyPropertyChanged interface and whenever change to any property takes place then you call service.
Anyone can suggest a good Design Pattern for reporting/monitoring status/progress of long processes.
Basically, I have a codebase that receives a "data-context" object:
public class DataContext : IDataContext
{
pulbic Dictionary<string, objects> Properties { get; private set; }
// Additional properties removed for simplicity...
}
Based on the provided context, a Task (not TPL-Task) object is created, with various subtasks.
During execution, the DataContext object is passed to the various sub-tasks, which can retrieve or update it.
For example, let's say that the main task is a "Copy files" task. The DataContext will have properties like the SourceFolder and TargetFolder, and perhaps a FilterFiles property (e.g. *.docx). Our main task will be a CopyFilesTasks, and it will have a "pipeline" of subtasks - Scan Folders, Scan Files, Filter Files, Copy Files, etc....
What I am looking for, is the best way to allow the task/sub-tasks to report their progress to the caller/executer.
In our example above, the changes in progress might be just "Copied file ABC.docx...", or perhaps something a bit more "complex", like "Scanning folder XYZ..."
I have considered the following options:
INotifyPropertyChanged: add a "Progress" property to DataContext
public string Progress { get; set { _progress = value; RaisePropertyChanged("Progress"); }
and have the code that created the DataContext object register to the PropertyChanged event. However, this seems like a too-simplistic approach...
ILog (using whatever logging framework you prefer): use an ILog instance in the various tasks/sub-tasks, and have the main-task executioner add it's own listener to the logging framework.
However this seemed like bending the logging mechanism to do things it was not supposed to do.
Udi Dahan's DomainEvents: The executioner of the task can regard the DataContext as a "domain", and therefore we can try to implement an "EventHandler" for a "ProgressChanged" event. In theory, this can be even used for more refined events, that happen in specific sub-tasks... But once again, it feels like forcing the concept...
My concerns include things like:
Progress might not be the only "event" that needs to be monitored - in our example above, we might want things more defined, like FolderHandled, FileCopied, etc., but we might not know the exact events when executing the tasks (remember - the subtasks are created based on the DataContext, and might result in different tasks being executed).
The context of running the tasks is not yet defined. For now, I'm just planning to run the tasks from the command-line application, so outputting to the command-line is needed for debugging. Later on, when I move this to a service, I might want to have a "listener" update a database with the task's progress (for example).
You can declare arguments for each possible operation type, say FileOperationEventArgs for file operation, DatabaseUpdateEventArgs for database operation etc.
public class FileOperationEventArgs : EventArgs
{
public readonly string SourceFolder;
public readonly string TargetFolder;
public FileOperationEventArgs(string sourceFolder, string targetFolder)
{
SourceFolder = sourceFolder;
TargetFolder = targetFolder;
}
}
public class DatabaseUpdateEventArgs : EventArgs
{
public readonly int RowsUpdated;
public DatabaseUpdateEventArgs(int rowsUpdated)
{
RowsUpdated = rowsUpdated;
}
}
OperationProgress class declares events for each operation type.
public class OperationProgress
{
public event EventHandler<FileOperationEventArgs> FileCopied;
public event EventHandler<DatabaseUpdateEventArgs> DatabaseUpdated;
public void OnFileCopied(FileOperationEventArgs a)
{
if(FileCopied != null)
FileCopied(this, a);
}
public void OnDatabaseUpdated(DatabaseUpdateEventArgs a)
{
if (DatabaseUpdated != null)
DatabaseUpdated(this, a);
}
}
OperationProgress will be specified when DataContext is created.
public class DataContext : IDataContext
{
public Dictionary<string, object> Properties { get; private set; }
public OperationProgress Progress { get; private set; }
public DataContext(OperationProgress progress)
{
Progress = progress;
}
}
Subtask implementation can update the progress.
public class FileCopySubTask
{
public void Execute(DataContext context)
{
context.Progress.OnFileCopied(new FileOperationEventArgs("c:/temp1", "c:/temp2"));
}
}
Consider BackgroundWorkers.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
They have their own reportprogress event on a separate UI thread.
WPF InteropBitmap can be created from shared memory, i.e.
Imaging.CreateBitmapSourceFromMemorySection()
In this case, we can update shared memory in another thread or process, and then after updating, calling InteropBitmap.Invalidate() to present the changes.
From the WPF source code, InteropBitmap is just a wrapper of IWICBitmap, but it doesn't expose IWICBitmap::lock which is used for exclusive writing.
So, how do I sync writing and reading of WPF InteropBitmap?
Updating occurs in user's thread.
Reading always occurs in WPF internal render thread via IWICBitmapSource::CopyPixels
Thanks
You can create a WrapperClass which exposed a lock object and the methods to manipulate the Image. Is some work but would work 100%
something like:
class InteropBitmapSyncWrapper
{
public InteropBitmapSyncWrapper(InteropBitmap wrappedBitmap)
{
WrappedBitmap = wrappedBitmap;
this.Lock = new Object();
}
public InteropBitmap WrappedBitmap
{
get;
set;
}
public Object Lock
{
get;
private set;
}
}