I made a TV-Player in c# using directshowlib-2005.
now I made a method to search for available channels.
I want this method to run in a different thread so my GUI won't freeze, but I get an error when I try to set the channel in the method. It can't find the IAMTVTuner interface in my graph, altough I know it's there.
If I don't use a different thread, the method works just fine (but my GUI freezes for a while)
I know it has to do something with apartments, but is there a way I can acces that interface in a different thread then the thread where created my graph in?
This problem is because some com classes or interfaces like in the DirectShowLib should be just accessed from the same thread that it was created on.
So the solution to this problem is to implement ISynchronizeInvoke "System.ComponentModel.ISynchronizeInvoke".
For example if you need to access methods in the class named Media that uses internally some classes or methods from the DirectshowLib in multithreading mode, you have to check if invoke required by using InvokeRequired and if true you have to access it via Invoke method.
To demonstrate how to implement ISynchronizeInvoke interface here is a snippet from a code that I develop some time ago in C# 2.0
public abstract class Media : ISynchronizeInvoke
{
//....
private readonly System.Threading.SynchronizationContext _currentContext = System.Threading.SynchronizationContext.Current;
private readonly System.Threading.Thread _mainThread = System.Threading.Thread.CurrentThread;
private readonly object _invokeLocker = new object();
//....
#region ISynchronizeInvoke Members
public bool InvokeRequired
{
get
{
return System.Threading.Thread.CurrentThread.ManagedThreadId != this._mainThread.ManagedThreadId;
}
}
/// <summary>
/// This method is not supported!
/// </summary>
/// <param name="method"></param>
/// <param name="args"></param>
/// <returns></returns>
[Obsolete("This method is not supported!", true)]
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
throw new NotSupportedException("The method or operation is not implemented.");
}
/// <summary>
/// This method is not supported!
/// </summary>
/// <param name="method"></param>
/// <param name="args"></param>
/// <returns></returns>
[Obsolete("This method is not supported!", true)]
public object EndInvoke(IAsyncResult result)
{
throw new NotSupportedException("The method or operation is not implemented.");
}
public object Invoke(Delegate method, object[] args)
{
if (method == null)
{
throw new ArgumentNullException("method");
}
lock (_invokeLocker)
{
object objectToGet = null;
SendOrPostCallback invoker = new SendOrPostCallback(
delegate(object data)
{
objectToGet = method.DynamicInvoke(args);
});
_currentContext.Send(new SendOrPostCallback(invoker), method.Target);
return objectToGet;
}
}
public object Invoke(Delegate method)
{
return Invoke(method, null);
}
#endregion//ISynchronizeInvoke Members
}
Related
Can someone explain whether or not I can call the below class "thread safe"?
As far as I know, we can call something thread safe if we are not breaking existing functionality
Example:
public class BackgroundWorker
{
private readonly IDictionary<string, RunningTask> _runningTasks = new ConcurrentDictionary<string, RunningTask>();
/// <summary>
/// Executes async job for the specified key, only one at a time.
/// </summary>
/// <param name="key"></param>
public void Enqueue(string key)
{
if (_runningTasks.ContainsKey(key))
{
_runningTasks[key].Repeat = true;
return;
}
_runningTasks[key] = new RunningTask();
ExecuteTask(key);
}
private void ExecuteTask(string key)
{
Task.Run(() =>
{
// Do something
if (_runningTasks[key].Repeat)
{
_runningTasks[key].Repeat = false;
ExecuteTask(key);
return;
}
_runningTasks.Remove(key);
});
}
private class RunningTask
{
/// <summary>
/// Flag to repeat a task after completion.
/// </summary>
public bool Repeat { get; set; }
}
}
I don't think so because _runningTasks is shared object and your method Enqueue is writing on this shared object. For example its possible when one thread already executed line number y, another thread will evaluate condition check in line number x as true - which might not be intention.
public void Enqueue(string key)
{
if (_runningTasks.ContainsKey(key)) /*say line no : x */
{
_runningTasks[key].Repeat = true;
return;
}
_runningTasks[key] = new RunningTask(); /*say line no:y*/
ExecuteTask(key);
}
Using ConcurrentDictionary will just ensure no two threads can read/write to/from the dictionary same time.
To your second point :
As far as I know, we can call something thread safe if we are not
breaking existing functionality
No this is not the definition of thread safe (might be ok to say one of desirable outcome in multi threaded environment) I would recommend to read this post for official meaning rather.
I have created an OracleUnitOfWork and Repository class like this:
public class OracleUnitOfWork : IOracleUnitOfWork
{
// Private properties
private readonly OracleConnection _connection;
private readonly OracleCommand _command;
private readonly Dictionary<Type, object> _repositories;
private Object thisLock = new Object();
/// <summary>
/// Default constructor
/// </summary>
/// <param name="config">The Cormar config class</param>
public OracleUnitOfWork(CormarConfig config)
{
// Create instances for our private properties
this._repositories = new Dictionary<Type, object>();
this._connection = new OracleConnection(config.ConnectionString);
this._command = new OracleCommand
{
Connection = this._connection,
CommandType = CommandType.StoredProcedure,
BindByName = true
};
// Open our connection
this._connection.Open();
}
/// <summary>
/// Gets the entity repository
/// </summary>
/// <typeparam name="T">The entity model</typeparam>
/// <returns></returns>
public IRepository<T> GetRepository<T>() where T : class, new()
{
// Lock the thread so we can't execute at the same time
lock (thisLock)
{
// If our repositories have a matching repository, return it
if (_repositories.Keys.Contains(typeof(T)))
return _repositories[typeof(T)] as IRepository<T>;
// Create a new repository for our entity
var repository = new Repository<T>(this._command);
// Add to our list of repositories
_repositories.Add(typeof(T), repository);
// Return our repository
return repository;
}
}
/// <summary>
/// Dispose
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Disposes of any attached resources
/// </summary>
/// <param name="disposing">A boolean indicating whether the object is being disposed</param>
protected virtual void Dispose(bool disposing)
{
// If we are disposing
if (disposing)
{
// Close our connection
this._connection.Close();
this._connection.Dispose();
this._command.Dispose();
}
}
}
public class Repository<T> : IRepository<T> where T : class, new()
{
// private properties
private readonly OracleCommand _command;
private Object thisLock = new Object();
/// <summary>
/// Default constructor
/// </summary>
/// <param name="command"></param>
public Repository(OracleCommand command)
{
this._command = command;
}
/// <summary>
/// Returns the datareader for the stored procedure
/// </summary>
/// <param name="storedProcedureName">The name of the SPROC to execute</param>
/// <param name="parameters">The parameters needed for the SPROC</param>
/// <returns></returns>
public async Task<IDataReader> ExecuteReaderAsync(string storedProcedureName, IList<OracleParameter> parameters = null)
{
// Set up our command
this.InitiateCommand(storedProcedureName, parameters.ToArray());
// Return our data reader
return await this._command.ExecuteReaderAsync();
}
/// <summary>
/// Create, updates or deletes an entity
/// </summary>
/// <param name="storedProcedureName">The name of the SPROC to execute</param>
/// <param name="parameters">The parameters needed for the SPROC</param>
public async Task CreateUpdateOrDeleteAsync(string storedProcedureName, IList<OracleParameter> parameters = null)
{
// Set up our command
this.InitiateCommand(storedProcedureName, parameters.ToArray());
// Execute our command
await this._command.ExecuteNonQueryAsync();
}
/// <summary>
/// Intiates the command object
/// </summary>
/// <param name="storedProcedureName">The name of the SPROC to execute</param>
/// <param name="parameters">An array of parameters</param>
private void InitiateCommand(string storedProcedureName, OracleParameter[] parameters)
{
// Lock the thread so we can't execute at the same time
lock (thisLock)
{
// Set up the command object
this._command.CommandTimeout = 1800;
this._command.FetchSize = 1000;
this._command.CommandText = storedProcedureName;
this._command.Parameters.Clear();
// If we have any parameters
if (parameters != null)
{
// Assign each parameter to the command object
this._command.Parameters.AddRange(parameters);
}
}
}
}
In my AutoFac module, I register the OracleUnitOfWork as a single instance like this:
builder.RegisterType<OracleUnitOfWork>().As<IOracleUnitOfWork>().SingleInstance();
For most queries, this is fine, but I seem to have a problem when trying to execute multiple queries simultaneously. It errors out on the ExecuteReaderAsync method in my repository and states:
Object reference not set to an instance of an object.
Sometimes I even get this error:
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
But I can't figure out how to fix the issue.
Prior to this I was getting issues with the GetRepository method, but when I added locking that fixed the issue. I can't do that to ExecuteReaderAsync method because it will no longer be asynchronous and I need it to be.
Does anyone know how to solve this issue?
For most queries, this is fine, but I seem to have a problem when
trying to execute multiple queries simultaneously.
You have a race condition, you're trying to access the same references across multiple threads and getting "spooky" behaviour.
You can't pass a mutable singleton across multiple threads like that, it will break. Either bite the bullet and use a a _lock or rethink your approach (i.e. Don't use a singleton).
Just remember, locks will kill your multi-threaded performance if not used correctly.
Kushan is right about OracleConnection not being thread safe. If you really need to execute multiple queries in the same time and you are not affected by the overhead, you can remove SingleInstance() and allow multiple instances to be built.
This way, each of your threads can obtain a new instance of OracleUnitOfWork and do its work independently (fetch data, perform changes, persist changes).
I've written a DLL that does a bunch of stuff. One of the things it does is to search through a lot of incoming messages for a specific message, clean up the message, and raise an event when the message is found, and pass the data via the EventArgs.
Currently the DLL is working but the routine that searches for the message is slowing everything down and making the system slow to respond because there is so much data to go through.
I would like to move this searching to it's own thread, and once the message is found have it raise an event on the main thread and pass the message data to the main thread. I know how to make a thread to do the work, but I do not know how to make the thread raise the event on the main thread and pass the data to it. Could someone tell me how to do this, or point to an example of it?
I've tried creating a delegate and triggering an event, which works but when I try to pass the data I get a cross thread exception.
Some details that may be important. There most likely won't be a GUI at all and will probably remain a console application. Messages will always be coming in and the DLL has to continuously search them. The message the DLL is looking for may come as often as 1 couple times a second or it may be days between the messages.
Update for a real simple project illustrating what I would like to do. This code is rough cause I threw it together to test this out.
If you follow the code you will see that everything runs fine until the line in the CollectData function where:
StatusUpdated(this, null);
is called. At this point it causes the cross thread exception because of the UI thread and the data Collection thread. I know I can fix this by using an invoke on the UI thread, but as mentioned above this will most likely not be used with any sort of GUI (but it should be able to handle it). So the cross thread exception needs to be fixed in the BuildResultsManager class, I think in the function BRMgr_StatusUpdated. How do I get the data (in this case the value of currentVal) to the UI thread without changing any code in the MainWindow class.
You can run this by creating a solution with 2 projects, 1 for the first 2 files as a dll. The second as a wpf project, referencing the dll, and put a textbox named status on the form.
Main Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace BuildResultsManager
{
/// <summary>
/// Delegate to notify when data has changed
/// </summary>
/// <param name="sender">unused</param>
/// <param name="e">unused</param>
public delegate void StatusUpdatedEventHandler(object sender, EventArgs e);
/// <summary>
/// Connects to the PLC via PVI and reads in all the build results data, conditions it, updates values and reads/store into the database
/// </summary>
public class BuildResultsManager
{
#region events
// Change in The Build Results Manger Status
public event StatusUpdatedEventHandler StatusUpdated;
#endregion
#region Local variables
private Thread collectionThread;
private string statusMessage;
DataCollector dataCollection;
#endregion
#region Properties
/// <summary>
/// Current Status of the Build Results manager
/// </summary>
public String StatusMessage
{
get
{
return statusMessage;
}
private set
{
statusMessage = value;
if (StatusUpdated != null)
StatusUpdated(this, null);
}
}
#endregion
#region Constructors
/// <summary>
/// Default constructor
/// </summary>
public BuildResultsManager()
{
StatusMessage = "successfully initialized";
// start the thread that will collect all the data
dataCollection = new DataCollector();
dataCollection.StatusUpdated += new DCStatusUpdatedEventHandler(BRMgr_StatusUpdated);
collectionThread = new Thread(new ThreadStart(dataCollection.CollectData));
collectionThread.Start();
}
/// <summary>
/// EVent to handle updated status text
/// </summary>
/// <param name="sender">unused</param>
/// <param name="e">unused</param>
void BRMgr_StatusUpdated(object sender, EventArgs e)
{
StatusMessage = dataCollection.currentVal.ToString();
}
#endregion
}
}
The class that will be doing all of the thread work:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Windows.Threading;
using System.Threading;
namespace BuildResultsManager
{
/// <summary>
/// Delegate to notify when data has changed
/// </summary>
/// <param name="sender">unused</param>
/// <param name="e">unused</param>
public delegate void DCStatusUpdatedEventHandler(object sender, EventArgs e);
/// <summary>
/// Handles all of the data collection and conditioning
/// </summary>
class DataCollector
{
#region events
// Change in The Build Results Manger Status
public event DCStatusUpdatedEventHandler StatusUpdated;
#endregion
private const long updateInterval = 1000;
private Stopwatch updateTimer;
public int currentVal;
#region local variables
private bool shouldStop;
#endregion
/// <summary>
/// Default Constructor
/// </summary>
public DataCollector()
{
shouldStop = false;
updateTimer = new Stopwatch();
updateTimer.Start();
}
/// <summary>
/// Main task that listens for new data and collects it when it's available
/// </summary>
public void CollectData()
{
currentVal = 5;
while (!shouldStop && currentVal < 10)
{
if(updateTimer.ElapsedMilliseconds > updateInterval)
{
currentVal++;
if (StatusUpdated != null)
{
StatusUpdated(this, null);
}
//reset the timer
updateTimer.Restart();
}
}
}
/// <summary>
/// Asks the thread to stop
/// </summary>
public void RequestStop()
{
shouldStop = true;
}
}
}
Code behind for the wpf project:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region Local variables
private string BRMgrStatus;
private BuildResultsManager.BuildResultsManager BRMgr;
#endregion
public MainWindow()
{
InitializeComponent();
// create an instance of the build manager
BRMgr = new BuildResultsManager.BuildResultsManager();
if(BRMgr != null)
{
status.Text = BRMgr.StatusMessage;
BRMgr.StatusUpdated += new StatusUpdatedEventHandler(BRMgr_StatusUpdated);
}
}
/// <summary>
/// EVent to handle updated status text
/// </summary>
/// <param name="sender">unused</param>
/// <param name="e">unused</param>
void BRMgr_StatusUpdated(object sender, EventArgs e)
{
BuildResultsManager.BuildResultsManager brm;
brm = (BuildResultsManager.BuildResultsManager)sender;
status.Text = brm.StatusMessage;
}
}
If you don't use a GUI there's no need to execute things on the same thread, just protect non-thread-safe resources with a locking mechanism (lock, mutex, etc) to avoid concurrent access and you're good.
I have been tasked with creating Java code with similar functionality to the code below. Currently I am struggling with understanding exactly what the code does and how to simulate the effect in Java.
#region "Send Aggregate Event"
/// <summary>
/// Delegate for async sending the AggregateEvent
/// </summary>
/// <param name="request"></param>
public delegate void SendAggregateEventAsync(AE request);
SendAggregateEventAsync _sendAggregateEventAsync;
/// <summary>
/// IAsyncResult pattern to async send the AggregateEvent
/// </summary>
/// <param name="request"></param>
/// <param name="callback"></param>
/// <param name="state"></param>
/// <returns></returns>
public IAsyncResult BeginSendAggregateEvent(AE request, AsyncCallback callback, Object state)
{
_sendAggregateEventAsync = new SendAggregateEventAsync(SendAggregateEvent);
return _sendAggregateEventAsync.BeginInvoke(request, callback, state);
}
public void EndSendAggregateEvent(IAsyncResult result)
{
object state = result.AsyncState;
_sendAggregateEventAsync.EndInvoke(result);
}
/// <summary>
/// Send an aggregate event to the Device Webserver
/// </summary>
/// <param name="request">The AggregateEvent request</param>
public void SendAggregateEvent(AE request)
{
if (request == null) throw new ArgumentNullException("request");
String message = ChangeDatesToUTC(MessageHelper.SerializeObject( typeof(AE), request), new String[] { "EventTime" }, url);
SendMessage(message);
}
#endregion
There are several other events all with similar code to the provided above. From the comments, I understand that the code is intended to asynchronously handle the SendAggregateEvent method. What I do not understand is why the delegate modifier is used, or how to replicate this type of asynchronous handling in Java.
Also from reading this thread
Java Delegates?
I understand that there is no "easy" way to simulate the delegate functionality in java. Is it necessary to have the delegate functionality to have the SendAggregateEvent method handled asynchronously? If not, can someone suggest how I would do this?
This is actually the old way of writing async code in C#, commonly referred to as the Async Programming Model
I am not familiar enough with java, but all you really need to replicate this code is to create a method that does the action synchronously SendAggregateEvent and a means to call that asynchronously SendAggregateEventAsync
More specifically to some of your questions. The delegate is only being used to encapsulate the SendAggregateEvent method so that it and its parameters can be invoked on a potentially different thread (keeping in mind that async is not necessarily multi-threaded)
It goes something like this:
var referenceToTaskBeingRun = BeginSomeMethod()
//the above wraps the actual method and calls it, returning a reference to the task
var results = EndSomeMethod(referenceToTaskBeingRun );
//the above sends the reference so that it can be used to get the results from the task.
//NOTE that this is blocking because you are now waiting for the results, whether they finished or not
The preferred way to do this now is to use the Task Parallel Library, which has a much easier to read code base.
So, all of that being said, the key to focus on this code would be that you just need a method and an async version of that method. The implementation should be up to you and your programming stack. Do not try to force another stack's implementation where it does not belong...especially an implementation that is not even the preferred methodology any longer.
According to How to asynchronously call a method in Java's answer, FutureTask is a good way in Java to asynchronously run a method. Here's some Java code that runs a task asynchronously (see it run at http://ideone.com/ZtjA5C)
import java.util.*;
import java.lang.*;
import java.util.concurrent.FutureTask;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
System.out.println("Before");
ExecutorService executorService = Executors.newFixedThreadPool(1);
FutureTask<Object> futureTask = new FutureTask<Object>(new Runnable() {
public void run()
{
System.out.println("Hello async world!");
}
}, null);
System.out.println("Defined");
executorService.execute(futureTask);
System.out.println("Running");
while (!futureTask.isDone())
{
System.out.println("Task not yet completed.");
try
{
Thread.sleep(1);
}
catch (InterruptedException interruptedException)
{
}
}
System.out.println("Done");
}
}
Is this an appropriate way of handling cross-thread operations?
Should I use a new property name, something like "EditValueThreadSafe" instead of overriding "EditValue"? I don't think there is an issue with the changes to the implementation of EditValue, as the base property is called regardless.
namespace MyApplication.Components
{
using System.Windows.Forms;
/// <summary>
/// Thread-safe implementation of the DevExpress.XtraEditors.ComboBoxEdit class.
/// </summary>
public class ComboBoxEditThreadSafe : DevExpress.XtraEditors.ComboBoxEdit
{
/// <summary>
/// Gets or sets the edit value.
/// </summary>
/// <value>The edit value.</value>
public override object EditValue
{
get
{
return base.EditValue;
}
set
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(delegate
{
this.SetEditValue(value);
}));
}
else
{
this.SetEditValue(value);
}
}
}
/// <summary>
/// Sets the edit value.
/// </summary>
/// <param name="value">The value.</param>
private void SetEditValue(object value)
{
base.EditValue = value;
}
}
}
You can also delegate to another method that does the work, and in that method, if on the wrong thread, (BeginInvoke returns true), then call the same method back again. Doing that that eliminates the need to duplicate code.
public class ComboBoxEditThreadSafe : DevExpress.XtraEditors.ComboBoxEdit
{
public override object EditValue
{
get
{
return base.EditValue;
}
set
{
SetValue(value);
}
}
private void delegate SetValueDlg(object valeu);
private void SetValue(object value)
{
if (this.InvokeRequired)
this.BeginInvoke(
(SetValueDlg)SetValue, // calls itself, but on correct thread
new object[] { value });
else
base.editValue = value;
}
}
You can also use the Action() generic class to eliminate need to create explicit delegate class...
public class ComboBoxEditThreadSafe : DevExpress.XtraEditors.ComboBoxEdit
{
public override object EditValue
{
get { return base.EditValue; }
set { SetValue(value); }
}
private void SetValue(object value)
{
if (this.InvokeRequired)
this.BeginInvoke(
new Action<object>(SetValue), // calls itself, but on correct thread
new object[] { value });
else
base.editValue = value;
}
}
It's thread-safe, yes, though be wary of overriding a property and fundamentally changing the behaviour. Changing the implentation is fine, but this property now behaves very differently, removing the possibility of a specific exception but introducing a possible deadlock or blocking condition, which impacts on the calling code.
So yes, this is the correct use of InvokeRequired & Invoke, but I'd recommend creating a separate, purpose-specific and thread-safe property that is advertised as such.
My UI methods like yours end up looking like this:
public void setStatusLabelText(String s)
{
if (footerStatusLabel.InvokeRequired) {
StringUpdateInvokeDelegate callback = new StringUpdateInvokeDelegate(setStatusLabelText);
this.Invoke(callback, new object[] { s });
}
else {
this.footerStatusLabel.Text = s;
}
}
(this may be old for .net these days - but the point is that you can just do the operation inside this method if you are already on the right thread - makes it a little less irritating to read, but still annoying compared to Java, IMO).
I'll inject my 2 cents here. The actual calls to InvokeRequired/BeginInvoke/Invoke are not entirely thread safe. (see Avoiding the woes of Invoke/BeginInvoke in cross-thread WinForm event handling?) I would recommend finding some way of isolating the calls to these in a single place, utility api, extension method, or the like. In the article above there is complete code for a class that wraps a delegate to provide thread-safe behavior.