I have this code, and have a function named STARTWORK(int THREADNR) which cannot be called by 2 threads. Basically all the work of my program is contained in this function, where in the WORKVOID1() and WORKVOID2() i use separate for() functions to run through the data, and the for() function is split in half so that the 2 functions cover half-half of the data to be much faster and work on multicore processor.The problem is that if there is only the main thread, it works like a charm, but if i try to split the STARTWORK() into 2 parts in WORKVOID1() and WORKVOID2() each in multiple threads it doesn't work, so please help me fix it.
public void OPTIMIZATION_ITERATION()
{
Thread WORK = new Thread(WORKVOID);
WORK.Name = "T1";
WORK.Start();
Thread WORK2 = new Thread(WORKVOID2);
WORK2.Name = "T2";
WORK2.Start();
}
public void WORKVOID()
{
for (ALPHA = 0.001; ALPHA <= 0.5; ALPHA += 0.001)
STARTWORK(1);
}
public void WORKVOID2()
{
for (ALPHA = 0.5; ALPHA <= 1; ALPHA += 0.001)
STARTWORK(2);
}
public void STARTWORK(int THREAD)
{
//.......bunch of calculations then it writes it to file
System.IO.StreamWriter WRITE = new System.IO.StreamWriter("OUTPUT_T"+THREAD+".txt", true);
WRITE.BaseStream.Seek(0, SeekOrigin.End);
WRITE.WriteLine(/*..calculations are written to file..*/);
WRITE.Close();
WRITE.Dispose();
}
The STARTWORK(int THREADNR) contains a parameter which will assign a number that will write the data to file so that the 2 will have different filenames, while ALPHA is a global double variable.
if your working in c# you might want to try this.
public void OPTIMIZATION_ITERATION()
{
Thread WORK = new Thread(new ThreadStart(WORKVOID));
WORK.Name = "T1";
WORK.Start();
Thread WORK2 = new Thread(new ThreadStart(WORKVOID2));
WORK2.Name = "T2";
WORK2.Start();
}
public void WORKVOID()
{
for (ALPHA = 0.001; ALPHA <= 0.5; ALPHA += 0.001)
STARTWORK(1);
}
public void WORKVOID2()
{
for (ALPHA = 0.5; ALPHA <= 1; ALPHA += 0.001)
STARTWORK(2);
}
I think the problem is ALPHA. As soon as you start the second thread you set it equal to the condition that the first thread is looking for (ALPHA <= .5), then the first thread increments ALPHA by .001. The net result is that the first thread is highly unlikely to write anything to the file (maybe one line, depending on timing).
Beyond that, I don't really see the point of trying to to do this in parallel, if you are writing to the same disk, it's not going to help anything. If the calculations you are doing are CPU intense, then it might be a better approach to make the calculations parallel and then write everything to disk after it's done, or in chunks if memory is an issue.
Global variables such as ALPHA cannot be used safely in multi-threaded contexts. This is because both threads are allowed to read/write at the exact same time which causes a race condition. I recommend you change your work methods to accept a double parameter. That way, each method would be using a local variable instead of a global shared variable.
Related
This is a short one that I have been unable to google a clear answer for.
Basically, I’m working with pixels but I want to put it on a second thread so UI and everything runs during expensive operations.
Are Vector4s, which are implicitly convertable to and from Color, allowed on other threads even though Unity isn’t thread safe?
Basically, how would I go about doing color operations without Color struct or Vector4s (if those don’t work either)?
In short: YES! (as long as you don't read/write them at the same time of course).
In long:
Only those parts that directly require or influence the Scene itself are not usable from any other threads than the Unity "main" thread. Unity immediately blocks it and shows a warning. So what you can not do is e.g. setting or getting Transform properties, trying to access .gameObject on any Component, anything related to Texture2D, stuff like GetComponent, Find etc.
structs, however, like Vector4, Color, Quaternion etc are just basic data containers holding some values and doing some pure mathematical operations on them ... they can be used in any background thread in order to process them.
Even your own MonoBehaviour can possibly be used in background threads (you just pass in a reference) as long as you access only those fields and only call those methods, that - again - don't immediately require or influence the Scene.
However, they are not "thread-safe" themselves, meaning there is no lock going on. So of course you have to assure yourself that your threads (Unity main thread and background thread(s)) have exclusive access to your values, meaning only exactly one thread may be reading and writing at the same time.
Something like this is completely valid:
private IEnumerator Start ()
{
Debug.Log("MainThread: Let's get some colors");
var stopWatch = new Stopwatch();
stopWatch.Restart();
var thread = new Thread(ColorThread);
thread.Start();
while (!ColorsReceived())
{
Debug.Log("MainThread: ... still waiting ...");
yield return new WaitForSeconds(0.5f);
}
lock(_lock)
{
Debug.Log($"MainThread: Got {colors.Length} colors after {stopWatch.ElapsedMilliseconds / 1000f} seconds");
}
}
private bool ColorsReceived()
{
lock(_lock)
{
return colors != null;
}
}
private void ColorThread()
{
Debug.Log("BackgroundThread: Started generating colors");
var output = new Color[1000];
var random = new System.Random();
for(var i = 0; i < output.Length;i++)
{
output[i] = new Color32((byte) random.Next(0, 256), (byte) random.Next(0, 256), (byte) random.Next(0, 256), (byte)random.Next(0,256));
}
// Do some havy stuff
Thread.Sleep(3000);
lock(_lock)
{
colors = output;
}
Debug.Log("BackgroundThread: Finished generating colors");
}
=>
MainThread: Lets's get some colors
MainThread: ... still waiting ...
BackgroundThread: Started generating colors
MainThread: ... still waiting ...
MainThread: ... still waiting ...
MainThread: ... still waiting ...
MainThread: ... still waiting ...
BackgroundThread: Finished generating colors
MainThread: Got 1000 colors after 3.19 seconds
I am working on voltmeter application, that draws voltage waveform. Hardware sends 1000 numbers (range 0 - 1023, always whole numbers) in string format per second through serial port.
public SerialPort serialPort = new SerialPort("COM3", 57600);
serialPort.Open();
String is converted into int and then drawn with DrawLine into PictureBox.
// variable declarations, all is int, runs in its own thread
while (blToMeasure) // true after clicking on button
{
iPrevY = iY;
iY = Int16.Parse(serialPort.ReadLine());
graphicsGraph.DrawLine(penBlack, iX, iPrevY, iX + 1, iY);
// only this thread is accessing PictureBox
iX++;
if (iX > picBoxGraph.Width)
{
graphicsGraph.Clear(SystemColors.Control);
iX = 0;
}
if (iY > picBoxGraph.Height)
{
}
}
Issue is that drawing lines itself is fast as it should be only for a couple of seconds, but gets gradually slower.
I tried Int.Parse, Int32.Parse and splitting thread function multiple ways using lock (graphicsGraph) (moving conditions with Clear into another thread) or using BlockingCollection<int> (moving DrawLine into another thread, away from Parse). Nothing seems to work and app still gets slower a couple of times after like a minute of running.
There isn't issue with hardware itself, checked with another software. Is this too fast for C#?
Solution:
I got the best results using Port.ReadTimeout = 1 and Port.DiscardInBuffer(). Also using Form.DoubleBuffered = true, but it doesn't make a huge difference in this particular case.
// constructor
Port.ReadTimeout = 1;
Form.DoubleBuffered = true;
Here is the loop itself:
btn.Click() // click to start measuring
{
Port.DiscardInBuffer();
blToMeasure = true;
}
while (blToMeasure) // true after clicking on button
{
iPrevY = iY;
try {
iY = Int16.Parse(serialPort.ReadLine());
}
catch
{
// exception logic
}
graphicsGraph.DrawLine(penBlack, iX, iPrevY, iX + 1, iY);
// only this thread is accessing PictureBox
iX++;
if (iX > picBoxGraph.Width)
{
graphicsGraph.Clear(SystemColors.Control);
iX = 0;
}
if (iY > picBoxGraph.Height)
{
}
}
When the app starts to read from the port, there is always accumulated data, because my hardware is sending numbers all the time, so I get rid of the buffer. Than the drawing of lines is not executed in differing spikes and the speed is constant. Analyzing the issue with Watch, I found out, that it occasionaly takes much longer to read this data and because of 1000 reads per second, it slows down. So to prevent slowing down, I used Port.ReadTimeout, that skips the read, if it takes too long.
The difference is visible, drawing no longer slows down and it keeps the same pace for minutes from what I've tried. I consider this sufficient solution for my issue, thank you!
I know of course that I can not draw onto the same Graphics object from different threads, but is it also true that I can not draw to different Graphics objects in different threads?
Consider the following console program:
class Program
{
static ThreadDrawer[] drawers;
static void Main(string[] args)
{
int numThreads = 8;
drawers = new ThreadDrawer[numThreads];
for (int i = 0; i < numThreads; i++)
{
drawers[i] = new ThreadDrawer();
drawers[i].Start();
}
for (int i = 0; i < numThreads; i++)
{
drawers[i].Wait();
}
Console.WriteLine("Complete.");
Console.ReadKey();
}
class ThreadDrawer
{
private Thread thread;
private AutoResetEvent resetEvent;
public ThreadDrawer()
{
thread = new Thread(DrawRandomCircles);
resetEvent = new AutoResetEvent(false);
}
public void Start()
{
thread.Start();
}
public void Wait()
{
resetEvent.WaitOne();
}
public void DrawRandomCircles()
{
Random r = new Random(Environment.TickCount);
using (Bitmap b = new Bitmap(1000, 1000))
using (Graphics g = Graphics.FromImage(b))
{
for (int i = 0; i < 100000; i++)
{
g.DrawEllipse(Pens.Red, new Rectangle(r.Next(1000), r.Next(1000), 200, 200));
}
}
resetEvent.Set();
}
}
}
The program creates a Bitmap in each thread and proceeds to draw random ellipses on it using a Graphics object, also generated per thread from the Bitmap.
Due to a requirement to build for .net2 the multithreading is implemented using Threads and AutoResetEvents instead of TPL.
The program executes without throwing an exception, but it executes serially. Using n threads multiplies execution time by n and it is clear to see using the task manager that only one core is being used.
Important to take note that none of this is tied to any UI element.
What is going on here? Is the Graphics object locking on a static object?
Here's a screen-shot of the concurrency analyzer I used to see what's going on with these threads:
Yes, you can see lots of red (blocking) with flecks of green (execution). The threads are taking turns entering a critical section that's acquired inside the internal GpGraphics::RenderDrawPath() function. The larger blobs of green is where the program actually drew the lines (I replaced DrawEllipse with DrawRectangle and got rid of the Random call).
There is some concurrency, you can for example see the RenderDrawPath() call being overlapped by the code that renders the anti-aliased lines, overall cpu load is around 35%. But there isn't much of it.
Nothing you can do about it of course. You get ahead by overlapping the logic in your own program to decide what to draw with the GDI+ calls. Which will normally happen, the test is too synthetic.
It seems like locking happens in unmanaged code, inside GDI+ library (unfortunately, this behavior is not mentioned in official docs).
Similar question: Parallelizing GDI+ Image Resizing .net
I'm not 100% sure.. but yes, there is a private static locking object in the Graphics class. It appears to be locked only from GetHalftonePalette, which in turn, is called whenever a Bitmap is initialized within the Graphics object. It would appear that this could be the cause of contention.
(Note: Initial findings after 5 minutes of using ILSpy.. not very in-depth)
I have a user control that shows a speed in a dial format (An image).
It has a single method: SetSpeed(int speed);
It then makes the dial move to the desired speed, from the last set speed. It does then in incriments. That is, it moves to the new speed.
Problem is, if the car is going 10km/h, and then goes (very quickly) to 100km/h, it takes the dial maybe 2 seconds to reach that speed... (It's not 100% real time - which is realistic .. it moves to the new speed).
But, if, before the dial gets to 100km/h, the person slows to 50km/h, I need to interupt the movement to 100, and start moving to 50. Regardless of the current position (not speed) of the dial, I need to change the 'target speed'.
My control is using a BackgroundWorker to handle the refreshing, and not lock the UI.
So, my call is very basic from the UI:
dial1.SetSpeed(int.Parse(value));
And then the user control does this:
BackgroundWorker bw = new BackgroundWorker();
public void SetSpeed(int speed)
{
while(bw.IsBusy)
{
Thread.Sleep(50);
}
bw.RunWorkerAsync(speed);
}
And the method that does the work:
private void UpdateSpeed(object sender, DoWorkEventArgs e)
{
var oldSpeed = airSpeed;
var newSpeed = (int) e.Argument;
if(oldSpeed <= newSpeed)
{
for (int i = oldSpeed; i < newSpeed; i++)
{
airSpeed++;
this.Invoke(new MethodInvoker(Refresh));
}
}
else
{
for (int i = oldSpeed; i > newSpeed; i--)
{
airSpeed--;
this.Invoke(new MethodInvoker(Refresh));
}
}
airSpeed = newSpeed;
}
It locks when I send it two values in quick succession...
How do I interrupt the thread, if it's running, and change the value?
(Also, I think my code to change the speed is bad - can that be made neater?)
You do not. You handle it in a proper way, with locks, and checking whether the value needs changing. You do NOT interrupt it.
Basically, you need a lock area between SetSpeed and the Refresh method, so that one blocks the other. Then, when you set speed and the thread is currently in a critical area, it simply waits until the update is finished.
And your UpdateSpeed makes no sense - the change (airspeed-- and airspeed++) should be timer driven... you currently change them in a "arbitrary" speed, depending on processor speed. No timing.
I need to make a console application that uses Kinect, with Kinect SDK and c#. Since it's a console application, I've found polling to be the best way to retrieve the frames I need to process. I'll need to retrieve frames from the depth camera and the rgb camera, do some processing on then in separate threads (one for the depth image and one for the rgb image), and give an output to the user for each of the two processed frames. The way I've been thinking about doing this is the following:
1 - create 2 threads, the first is on the method that polls the rgb camera and do the processing, the second is on the method that polls the depth camera and do the processing
2 - Start the threads
3 - enter a while some stop condition loop
4 - check separately if each thread is alive, if not, create them again and start them again
I've made a test program that follows those steps and it works, but I'm not sure it's the best way of doing it. My test program is
class Program
{
private static ClassExecutioner Executioner;
private static Class1 Cls;
static void Main(string[] args)
{
Executioner = new ClassExecutioner();
Cls = new Class1();
Thread fThread = new Thread(new ThreadStart(processA));
Thread sThread = new Thread(new ThreadStart(processB));
fThread.Start();
sThread.Start();
while (true)
{
if (!fThread.IsAlive)
{
fThread = new Thread(new ThreadStart(processA));
fThread.Start();
}
if (!sThread.IsAlive)
{
sThread = new Thread(new ThreadStart(processB));
sThread.Start();
}
}
}
static void processA()
{
String frameA = Cls.pollA();
Executioner.CallA(frameA);
}
static void processB()
{
String frameB = Cls.pollB();
Executioner.CallB(frameB);
}
}
Class 1 methods represent the polling of the cameras on kinect
class Class1
{
private int a;
private int b;
public Class1()
{
a = 0;
b = 0;
}
public String pollA()
{
String frame = "this is " + a % 100;
a++;
return frame;
}
public String pollB()
{
String frame = "I am " + b % 100;
b++;
return frame;
}
}
Executioner represents the methods that process the frames obtained from Kinect
class ClassExecutioner
{
public ClassExecutioner()
{
}
public void CallA(String frameA)
{
Random rand = new Random();
int time = rand.Next() % 1000000000;
//'processing' - wait some time
for (int i = 0; i < time; i++)
{
}
// finishes the processing of the 'frame' from stream A
Console.WriteLine(frameA);
}
public void CallB(String frameB)
{
Random rand = new Random();
int time = rand.Next() % 1000000000;
// 'processing' - wait some time
for (int i = 0; i < time; i++)
{
}
// finishes the processing of the 'frame' from stream B
Console.WriteLine(frameB);
}
}
The program is very simple but ilustrates well what I want to do with the Kinect streams. The problem is, I'm not sure this is the best way of doing it or even if this is gonna work at all on a practical, Kinect application. Keep in mind that, for now, each processing (depth and rgb) doesn't need information from the other.
Thanks in advance!
It might be cool to look into the ReactiveExtensions framework. It deals with async event streams very cleanly.
You can write LINQ against the data sources and do very interesting composable operations.
http://msdn.microsoft.com/en-us/data/gg577609.aspx
You basically would have two IEnumerable sequences (the things that loop infinitely) that yield out the frame at the given interval. You can then "query" these sequences using Rx. RX handles all the complicated threading issues for you and makes your consumer code clean and simple.
To be clear, you don't want to be creating new threads each time. You can create two infinite enumerables that each run on their own thread and yield out the result on each iteration. That way they don't even "die"