I am writing a code in c# to do image processing. I want to use threading and i suppose threading in WPF application is little different. I tried to run thread but it only works when the function is void(), i.e does not take any arguments.
However, my function is taking 3 arguemnts like this
frame_extract.Frame_Processing(_colorFrame_, widht, height);
So therefore the following does not work
depth_Threads = new System.Threading.Thread(**) since ** takes on void() type.
perhaps i am missing something, but my question is how can i work with threading for functions that take arguments.
Maybe you could use the TPL.
It should then be something like:
Task.Factory.StartNew(() => frame_extract.Frame_Processing(_colorFrame_, widht, height));
But be aware that you might have to marshal to the ui-thread.
If you want to create the thread in the ui thread and want the new thread to interact with mentioned ui thread, something like the following should work:
var task = new Task(() => frame_extract.Frame_Processing(_colorFrame_, widht, height));
task.Start(TaskScheduler.FromCurrentSynchronizationContext());
That should work.
I'm not 100% sure if that's what you want, but I think you need to do this :
depth_Threads = new System.Threading.Thread(()=>frame_extract.Frame_Processing(_colorFrame_, widht, height));
It depends on what values you are passing in. Sometimes if you are using objects, they are locked to a given thread in which case you need to create duplicates prior and then pass the duplicates into the new thread.
Do the following. Your method should receive single object argument like this void SomeVoid(object obj). Make an object array with all variables that you want to pass to the method SomeVoid like this object[] objArr = { arg1, arg2, arg3 }; and then call the Start method of thread object with objArr argument since the Start() method receives one object parameter. Now back to your method, cast and obj received from Start method to an object array like this object arr = obj as object[]; and then you can access those 3 arguments like this arr[0] arr[1] and arr[2]
You can use the ParameterizedThreadStart class.
1) Create a class who will holds your three arguments
public class FrameProcessingArguments
{
public object ColorFrame { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}
2) Modify your Frame_Processing method to take as parameter an instance of Object and inside it, cast that instance as a FrameProcessingArguments
if (arguments == null) throw new NullArgumentException();
if(arguments.GetType() != typeof(FrameProcessingArguments)) throw new InvalidTypeException();
FrameProcessingArguments _arguments = (FrameProcessingArguments) arguments;
3) Create and start your thread
FrameProcessingArguments arguments = new FrameProcessingArguments()
{
ColorFrame = null,
Width = 800,
Height = 600
}
Thread thread = new Thread (new ParameterizedThreadStart(frame_extract.Frame_Processing));
// You can also let the compiler infers the appropriate delegate creation syntax:
// and use the short form : Thread thread = new Thread(frame_extract.Frame_Processing);
thread.Start (arguments);
Related
I'm writing a program that will analyze changes in the stock market.
Every time the candles on the stock charts are updated, my algorithm scans every chart for certain pieces of data. I've noticed that this process is taking about 0.6 seconds each time, freezing my application. Its not getting stuck in a loop, and there are no other problems like exception errors slowing it down. It just takes a bit of time.
To solve this, I'm trying to see if I can thread the algorithm.
In order to call the algorithm to check over the charts, I have to call this:
checkCharts.RunAlgo();
As threads need an object, I'm trying to figure out how to run the RunAlgo(), but I'm not having any luck.
How can I have a thread run this method in my checkCharts object? Due to back propagating data, I can't start a new checkCharts object. I have to continue using that method from the existing object.
EDIT:
I tried this:
M4.ALProj.BotMain checkCharts = new ALProj.BotMain();
Thread algoThread = new Thread(checkCharts.RunAlgo);
It tells me that the checkCharts part of checkCharts.RunAlgo is gives me, "An object reference is required for the non-static field, method, or property "M4.ALProj.BotMain"."
In a specific if statement, I was going to put the algoThread.Start(); Any idea what I did wrong there?
The answer to your question is actually very simple:
Thread myThread = new Thread(checkCharts.RunAlgo);
myThread.Start();
However, the more complex part is to make sure that when the method RunAlgo accesses variables inside the checkCharts object, this happens in a thread-safe manner.
See Thread Synchronization for help on how to synchronize access to data from multiple threads.
I would rather use Task.Run than Thread. Task.Run utilizes the ThreadPool which has been optimized to handle various loads effectively. You will also get all the goodies of Task.
await Task.Run(()=> checkCharts.RunAlgo);
Try this code block. Its a basic boilerplate but you can build on and extend it quite easily.
//If M4.ALProj.BotMain needs to be recreated for each run then comment this line and uncomment the one in DoRunParallel()
private static M4.ALProj.BotMain checkCharts = new M4.ALProj.BotMain();
private static object SyncRoot = new object();
private static System.Threading.Thread algoThread = null;
private static bool ReRunOnComplete = false;
public static void RunParallel()
{
lock (SyncRoot)
{
if (algoThread == null)
{
System.Threading.ThreadStart TS = new System.Threading.ThreadStart(DoRunParallel);
algoThread = new System.Threading.Thread(TS);
}
else
{
//Recieved a recalc call while still calculating
ReRunOnComplete = true;
}
}
}
public static void DoRunParallel()
{
bool ReRun = false;
try
{
//If M4.ALProj.BotMain needs to be recreated for each run then uncomment this line and comment private static version above
//M4.ALProj.BotMain checkCharts = new M4.ALProj.BotMain();
checkCharts.RunAlgo();
}
finally
{
lock (SyncRoot)
{
algoThread = null;
ReRun = ReRunOnComplete;
ReRunOnComplete = false;
}
}
if (ReRun)
{
RunParallel();
}
}
StateObjClass State = (StateObjClass)StateObj;
Can someone explain the method of initialization of 'State'. Need help in understanding the above statement.
Surrounding Code:
private class StateObjClass
{
// Used to hold parameters for calls to TimerTask.
public int SomeValue;
public System.Threading.Timer TimerReference;
public bool TimerCanceled;
}
public void RunTimer()
{
StateObjClass StateObj = new StateObjClass();
StateObj.TimerCanceled = false;
StateObj.SomeValue = 1;
System.Threading.TimerCallback TimerDelegate =
new System.Threading.TimerCallback(TimerTask);
// Create a timer that calls a procedure every 2 seconds.
// Note: There is no Start method; the timer starts running as soon as
// the instance is created.
System.Threading.Timer TimerItem =
new System.Threading.Timer(TimerDelegate, StateObj, 2000, 2000);
// Save a reference for Dispose.
StateObj.TimerReference = TimerItem;
// Run for ten loops.
while (StateObj.SomeValue < 10)
{
// Wait one second.
System.Threading.Thread.Sleep(1000);
}
// Request Dispose of the timer object.
StateObj.TimerCanceled = true;
}
private void TimerTask(object StateObj)
{
StateObjClass State = (StateObjClass)StateObj;
// Use the interlocked class to increment the counter variable.
System.Threading.Interlocked.Increment(ref State.SomeValue);
System.Diagnostics.Debug.WriteLine("Launched new thread " + DateTime.Now.ToString());
if (State.TimerCanceled)
// Dispose Requested.
{
State.TimerReference.Dispose();
System.Diagnostics.Debug.WriteLine("Done " + DateTime.Now.ToString());
}
}
It would help if you'd show surrounding code, but I suppose StateObj is probably declared as a different type as StateObjClass, like foo here:
object foo = new Foo();
Foo foo2 = (Foo)foo;
It is a Foo, but foo is declared as object, so whenever you use foo in your code, the compiler sees it as object.
In order to assign it to a more derived variable, like foo2, you'll have to cast foo to Foo.
If you don't the compiler will complain:
object foo = new Foo();
Foo foo2 = foo;
Cannot implicitly convert type 'object' to 'Foo'
It isn't really initialized. The () notation in this sense is actually a type cast. So StateObj must inherit from StateObjClass, and it is just being cast to that here and assigned to the State variable.
It is hard to know exactly why it is being done here, as there is only really one line of code with no context.
This is commonly done to specify which set of methods to expose if the StateObj has multiple overloads.
I have a form. On button click, it should redirect to a dll wherein there are 2 classes.
Classxyz:
Has 2 threads.
Thread 1: should have the method that inserts a string into an array
Thread 2: should have the method that returns the first element from the array
Classarray:
The array is in a classarray.
My problem:
I am not able to understand if my threads are performing their tasks.
Class xyz:
public void ToDo(string str)
{
ThreadObject firstThreadObject = new ThreadObject();
firstThreadObject.str = str;
Thread firstThread = new Thread(DoWorkpeek);
firstThread.Start(firstThreadObject);
ThreadObject secondThreadObject = new ThreadObject();
secondThreadObject.str = str;
Thread secondThread = new Thread(DoWorkenque);
secondThread.Start(secondThreadObject);
firstThread.Abort();
secondThread.Abort();
}
public void DoWorkpeek(object parameter)
{
ThreadObject threadObject = parameter as ThreadObject;
str1 = objq.queuepeek(threadObject.str);
MessageBox.Show(str1);
}
public void DoWorkenque(object parameter)
{
ThreadObject threadObject = parameter as ThreadObject;
objq.enqueue(threadObject.str);
}
Is my code correct?
MessageBox.show(str1);
is not showing.
First of all, Join() the threads, don't Abort() them.
Second, you could use a ParameterizedThreadStart object to start the threads, like so:
Thread firstThread = new Thread(new ParameterizedThreadStart(DoWorkpeek));
firstThread.Start(str);
...
firstThread.Join();
secondThread.Join();
Also, make sure that your objq object is accessible by both threads (e.g. is static) and lock it when accessing, like so:
ThreadObject threadObject = parameter as ThreadObject;
lock(objq)
str1 = objq.queuepeek(threadObject.str);
MessageBox.Show(str1);
Also, instead of using MessageBox.Show(str1), you could use System.Diagnostics.Debug.WriteLine(str1) and write to the Debug output window.
I wrote some sample code where I have an Action delegate declared in a method body where two params are passed and then consumed by the delegate code without those params being passed into the delagte. It seems cleaner to me to explictely pass in these params to the delegate too, but in this case I am not, and this code would work fine.
I am wondering how .NET keeps these references available in the export delegate that is now running on a new thread.
public void MyMethod(string name, ComplexObject myObj)
{
Action export = () => {
//do something with name
name = name + name;
//do something with complex reference object
myObj.SomeMethod(name);
};
// do more work
// example launch export on a new thread
System.Threading.Thread newThread = new System.Threading.Thread(new System.Threading.ThreadStart(export));
newThread.Start();
}
The compiler creates a special type that keeps those variables. Then, instead of storing those variables on the stack, it instantiates an instance of that type every time you call that method. Then, the anonymous delegates use a reference to that new instance to get access to those variables.
Scenario
I have a line of code whereby I pass a good number of parameters into a method.
CODE as described above
foreach(Asset asset in assetList)
{
asset.ContributePrice(m_frontMonthPrice, m_Vol, m_divisor, m_refPrice, m_type,
m_overrideVol, i, m_decimalPlaces, metalUSDFID, metalEURFID);
}
What I really want to do...
What I really want to do is spawn a new thread everytime I call this method so that it does the work quicker (there are a lot of assets).
Envisaged CODE
foreach(Asset asset in assetList)
{
Thread myNewThread =
new Thread(new ThreadStart(asset.ContributePrice (m_frontMonthPrice, m_Vol,
m_divisor, m_refPrice, m_type, m_overrideVol, i, m_decimalPlaces, metalUSDFID,
metalEURFID)));
myNewThread.Start();
}
ISSUES
This is something which has always bothered me......why can't I pass the parameters into the thread.....what difference does it make?
I can't see a way around this that won't involve lots of refactoring......
.......This is an old application, built piece by piece as a result of feature creep.
Therefore, the code itself is messy and hard to read/follow.
I thought I had pinpointed an area to save some time and increase the processing speed but now I've hit a wall with this.
SUGGESTIONS?
Any help or suggestions would be greatly appreciated.
Cheers.
EDIT:
I'm using .Net 3.5.......I could potentially update to .Net 4.0
If you're using C# 3, the easiest way would be:
foreach(Asset asset in assetList)
{
Asset localAsset = asset;
ThreadStart ts = () => localAsset.ContributePrice (m_frontMonthPrice, m_Vol,
m_divisor, m_refPrice, m_type, m_overrideVol, i,
m_decimalPlaces, metalUSDFID, metalEURFID);
new Thread(ts).Start();
}
You need to take a "local" copy of the asset loop variable to avoid weird issues due to captured variables - Eric Lippert has a great blog entry on it.
In C# 2 you could do the same with an anonymous method:
foreach(Asset asset in assetList)
{
Asset localAsset = asset;
ThreadStart ts = delegate { localAsset.ContributePrice(m_frontMonthPrice,
m_Vol, m_divisor, m_refPrice, m_type, m_overrideVol, i,
m_decimalPlaces, metalUSDFID, metalEURFID); };
new Thread(ts).Start();
}
In .NET 4 it would probably be better to use Parallel.ForEach. Even before .NET 4, creating a new thread for each item may well not be a good idea - consider using the thread pool instead.
Spawning a new thread for each task will most likely make the task run significantly slower. Use the thread pool for that as it amortizes the cost of creating new threads. If you're on .NET 4 take a look at the new Task class.
If you need to pass parameters to a thread when starting it, you must use the ParameterizedThreadStart delegate. If you need to pass several parameters, consider encapsulating them in a type.
You could use ParameterizedThreadStart. You'll need to wrap all of your parameters into a single object. (Untested code below).
struct ContributePriceParams
{
public decimal FrontMonthPrice;
public int Vol;
//etc
}
//...
foreach(Asset asset in assetList)
{
ContributePriceParams pStruct = new pStruct() {FrontMonthPrice = m_frontMonthPrice, Vol = m_vol};
ParameterizedThreadStart pStart = new ParameterizedThreadStart(asset.ContributePrice);
Thread newThread = new Thread(pStart);
newThread.Start(pStruct);
}