Reputation: 847
I have a problem that I have a service that will open a camera stream, take pictures and close it. The interface provides 3 methods for this:
public static void StartCameraService(string cameraName);
public static string TakePicture();
public static void StopCameraService();
These three work but I need to put TakePicture in a separate thread because the program I'm using requires to do so (Canoe, vector software), it is dotnet interpreter/compiler inside the tool. Now if I put that method in a separate thread it won't work because the camera is not initialized. Is there a way to call StartCameraService and StopCameraService on the main thread and execute the TakePicture in a separate thread?
The problem is that if I start the takepicture in a separate thread that the camera is not initialized because the start and stop is done in the main thread. Is there a way to share the state of this?
Upvotes: 0
Views: 111
Reputation: 36371
Is there a way to call StartCameraService and StopCameraService on the main thread and execute the TakePicture in a seperate thread?
Sure, there are a whole bunch of ways to ask the main thread to execute some piece of code, for example Dispatcher.Invoke, but see also SynchronizationContext, Control.Invoke and TaskScheduler.FromSynchronizationContext. All of them will in effect send a message to the UI message loop to do something. Some methods, like the Dispatcher.Invoke, will run synchronously, so will wait for the UI thread to complete. Others will just send the message and continue.
But when doing anything multi threaded you need to check the requirements of the object you are using. In many cases it is sufficient to use locks to ensure only a single thread uses the object at any one time. But some objects can only be used from the thread that created it, or only from the UI thread. So you might want to also run TakePicture
on the UI thread. To return a result you would need some temporary variable to store intermediate results:
public static string TakePicture(){
string temp = "";
Application.Current.Dispatcher.Invoke(() => temp = TakePictureOnMainThread());
return temp;
}
However, if at all possible I would recommend using a static factory method instead:
public interface IMyCamera : IDisposable{
string TakePicture();
}
...
public static IMyCamera ConnectToCamera(string cameraName){...}
This lets you create a camera object, use said object to take pictures, and dispose it, all on the same thread. Greatly reducing the risk of mistakes.
Also, note that multi threaded programming is difficult. It is notorious for causing very difficult bugs. So you should study the topic a fair bit before doing anything serious involving multiple threads.
Upvotes: 2