Fire and forget method in C# [duplicate] - c#

This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed 6 years ago.
Fire and forget method in C#
I refered different issues for 'Fire and Forget in C#'
i.e.
Simplest way to do a fire and forget method in C#?
.
.
and few several,
but i have an another issue with the same.i wrote following code
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
//fireAway(i);
Task.Factory.StartNew(() => fireAway(i));
}
Console.WriteLine("Main Finished");
Console.Read();
}
public static void fireAway(int i)
{
System.Threading.Thread.Sleep(5000);
Console.WriteLine("FireAway" + i);
}
where i am expecting output like
Main Finished
FireAway0
FireAway1
FireAway2
FireAway3
FireAway4
but output is
Main Finished
FireAway5
FireAway5
FireAway5
FireAway5
FireAway5
very honestly i am new to threading concept, i need help. How can i meet with expected output..?

The threads are started after the loop is finished. When the loop is finished the value of i is 5. You have to capture the value of i before you send it to StartNew(..)
for (int i = 0; i < 5; i++)
{
int tmp = i;
Task.Factory.StartNew(() => fireAway(tmp));
}

You should pass parameter to your method, not use i, because the method will start to execute only after you finish to iterate, see here

Related

How to perform an async UI update in C# WPF? [duplicate]

This question already has answers here:
How to put delay before doing an operation in WPF
(2 answers)
Closed last month.
I have a simple C# .NET WPF app that should display all pictures of a folder, each for half a second using an image element. PollPic is a property (of variable pollPic). currImageFilename was declared above. I aimed to use Invoke/BeginInvoke in order to update the UI. The function where this code belongs to is a async function, that is called (with await) from a button click event.
When I have 6 pictured in the folder, each has been read and and sleep was called 6 times but only the last picture was displayed in the end. Where is my general thinking mistake here?
Thanks everybody.
if (picPath != "")
{
string[] pollPicList = Directory.GetFiles(picPath);
if (pollPicList.Length > 0)
{
for (int i = 0; i < pollPicList.Length; i++)
{
currImageFilename = pollPicList[i];
PollPic = new BitmapImage(new Uri(currImageFilename));
this.Dispatcher.BeginInvoke(new Action(() => ShowDetectPic(PollPic)));
System.Threading.Thread.Sleep(500);
}
}
}
Unsuccessfully tried to use Task.Run instead.
Also not working Task t1 = new Task(() => ShowDetectPic(PollPic));
You can't sleep the GUI thread or nothing will render. Your async code needs to be the waiting, not whatever else it is you're doing there.
async ... Function()
{
string[] pollPicList = Directory.GetFiles(picPath);
if (pollPicList.Length > 0)
{
for (int i = 0; i < pollPicList.Length; i++)
{
currImageFilename = pollPicList[i];
PollPic = new BitmapImage(new Uri(currImageFilename));
ShowDetectPic(PollPic);
await Task.Delay(500);
}
}
}

For loop incrementing to thread assignment [duplicate]

This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed 3 months ago.
Been working on a program recently and have a question about a problem I ran into. I've solved it, but don't know why it's happening:
for(int i = 0; i<10; i++)
{
Thread t = new Thread (() => {(does stuff, uses "i")});
}
Essentially I have 10 known processes I want to run on separate threads. In the thread, the value of the incrementor "i" is used to assign an object to a position in another array (I use locking). Now if I run it as is, I get an out of bounds error and when I debug with code breaks, I find that on that last loop i is equal to 10, when the last value should be 9. When this code isn't threaded, it works perfectly fine.
I decided to try and assign the incrementer to a local variable inside the thread:
for(int i = 0; i<10; i++)
{
Thread t = new Thread (() =>
{
localI=i;
(does stuff, uses "localI")
});
}
This had the same issue. I did more reading online and tried a different ordering of it:
for(int i = 0; i<10; i++)
{
localI=i;
Thread t = new Thread (() =>
{
(does stuff, uses "localI")
});
}
And this code works. I can't at all figure out why this works, but the second example didn't. Could anyone help me figure it out?
Thanks
Effectively there are 11 threads, your main thread running the for loop and the threads you spawn.
By the time your 10 new threads run the main loop might well be finished and the value of i will be 10. If you then use this to index an array you will get the out of bounds error.
Your third example assigns i to the localI var, this will keep its value and the individual threads will use that saved value of localI.
It`s simple.
The i variable is run on main thread and for loop reaches 10 value even before the child thread initiates. So, you can add a local variable outside of child threads to get fixed value on every loop.
And, for loop set 10 on i variable, but not run loop, because gets false on checks.
Simple test:
class Program
{
static void Main(string[] args)
{
Test c = new Test();
Console.WriteLine("NonLocal:");
Console.WriteLine(string.Join(",", c.NonLocal));
Console.WriteLine();
Console.WriteLine("Local:");
Console.WriteLine(string.Join(",", c.Local));
Console.ReadLine();
}
}
class Test
{
public object locker;
public List<object> NonLocal; // use List<> for dynamic array
public object[] Local;
public Test()
{
this.locker = new object();
this.NonLocal = new List<object>();
this.Local = new object[10];
// child thread pool
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
int localI = i;
Thread t = new Thread(() =>
{
lock (locker)
{
// adding to result only index
// to see value on i variable on this point
this.NonLocal.Add(i);
// using a fixed local variable
this.Local[localI] = localI;
}
});
threads.Add(t);
t.Start();
}
// wait until threads end
while (true)
{
if (!threads.Any(x => x.IsAlive)) break;
}
}
}

why "lock" keyword a object argument [duplicate]

This question already has answers here:
C# "lock" keyword: Why is an object necessary for the syntax?
(3 answers)
Closed 4 years ago.
I do not speak English and I use translator.
I'm wondering when I'm studying thread synchronization.
class MainApp
{
static public int count = 0;
static private object tLock = new object();
static void plus()
{
for (int i = 0; i < 100; i++)
{
lock (tLock)
{
count++;
Console.WriteLine("plus " + count);
Thread.Sleep(1);
}
}
}
static void minus()
{
for (int i = 0; i < 100; i++)
{
lock (tLock)
{
count--;
Console.WriteLine("minus " + count);
Thread.Sleep(1);
}
}
}
static void Main()
{
Thread t1 = new Thread(new ThreadStart(plus));
Thread t2 = new Thread(new ThreadStart(minus));
t1.Start();
t2.Start();
}
}
Simple thread studying.
static private object tLock = new object();
lock (tLock) << argument value, why object argument??
Why have an object argument on lock?
Well, because it's convenient.
First of all, it's obvious in your code example that you need some shared state between the calls to lock, to declare that two different sections of code are mutually exclusive. If the syntax was just lock { } without a parameter, like this:
public void DoSomestuff()
{
lock
{
// Section A
}
}
public void DoOtherStuff()
{
lock
{
// Section B
}
}
Then either all locks would be mutually exclusive, or would impact only their individual portion of code (so two threads could execute section A and B concurrently, but only one thread at a time could execute A). This would greatly reduce the usefulness of the keyword.
Now that we established that we need a shared state, what this state should be? We could have used a string:
lock ("My Section")
{
// Section A
}
It would work but has a few drawbacks:
You expose yourself to potential collisions between the name of different sections in different libraries
It means that the runtime has to keep a kind of table to associate the string to a lock. Nothing too difficult, but that's some overhead
Instead, the .NET authors went for using an object argument. This solves problem 1/, as you know that another library won't have a reference to your object unless you willingly give it. But this also solves problem 2/, because this allows the runtime to store the lock in the actual object header. That's a pretty neat optimization.
Consider the following (without lock):
for (int i = 0; i < 1000; i++)
{
count++;
Console.WriteLine("plus " + count);
Thread.Sleep(1);
}
If two threads run simultaneously:
First thread adds one to count which is now 1.
Now second thread takes over and adds one to count which is now 2.
Second thread continues to print plus 2 and loops and again adds one to count which is now 3.
Now the first thread takes over and prints plus 3 which was not intended since count was 1 when WriteLine was to be called.
When adding a locking mechanism (lock) the developer makes sure that a part of the code is atomic, i.e. is run in sequence without interruption.
for (int i = 0; i < 1000; i++)
{
lock (tLock)
{
count++;
Console.WriteLine("plus " + count);
Thread.Sleep(1);
}
}
If you follow the same pattern here:
First thread adds one to count which is now 1.
Now second thread tries to take over but has to wait until the lock is released by the first thread.
First thread prints plus 1 and releases the lock.
Now second thread can take over and add one to count which is now 2.
First thread tries to take over but has to wait until the second thread releases the lock.
Second thread prints plus 2 and releases the lock.
As you can see the increment and WriteLine are now synchronized operations.
Edit
After you changed the question:
The lock keyword requires an object of reference type. It doesn't have to be an object. It can also be a class, interface, delegate, dynamic or string.
public static string a = string.Empty;
public static void Main()
{
lock(a)
{
Console.WriteLine("Hello World");
}
}
See the documentation for more information.

IProgress<T> and Parallel.ForEach Sync Issues

I'm running into a sync issue involving reporting progress inside of a Parallel.ForEach. I recreated a simplified version of the problem in a Console App. The example actually only uses one item in the list. Here's the code:
class Program
{
static void Main(string[] args)
{
int tracker = 0;
Parallel.ForEach(Enumerable.Range(1, 1), (item) =>
{
var progress = new Progress<int>((p) =>
{
tracker = p;
Console.WriteLine(String.Format("{0}", p));
});
Test(progress);
});
Console.WriteLine("The last value is: {0}", tracker);
Console.ReadKey();
}
static void Test(IProgress<int> progress)
{
for (int i = 0; i < 20; i++)
{
progress.Report(i);
}
}
}
As you can see, the line I expect to see last isn't output last and doesn't contain 20. But if I remove progress reporting and just write to output in the for loop like this:
class Program
{
static void Main(string[] args)
{
int tracker = 0;
Parallel.ForEach(Enumerable.Range(1, 1), (item) =>
{
tracker = Test();
});
Console.WriteLine("The last value is: {0}", tracker);
Console.ReadKey();
}
static int Test()
{
int i;
for ( i = 0; i < 20; i++)
{
Console.WriteLine(i.ToString());
}
return i;
}
}
it behaves like I expect. As far as I know, Parallel.ForEach creates a Task for each in item in the list and IProgress captures the context in which it's created on. Given it's a console app I didn't think that would matter. Help please!
The explanation is pretty much exactly what's written in the docs:
Any handler provided to the constructor or event handlers registered with the ProgressChanged event are invoked through a SynchronizationContext instance captured when the instance is constructed. If there is no current SynchronizationContext at the time of construction, the callbacks will be invoked on the ThreadPool.
By using Progress<T>.Report you're effectively queueing 20 tasks on the thread pool. There's no guarantee as to what order they're executed in.

confused about dangers of lock(this) [duplicate]

This question already has answers here:
Why is lock(this) {...} bad?
(18 answers)
Closed 8 years ago.
I wanted to understand dangers of lock(this) with some code example. With the code, if everything works well I expect to see 1000 at the end of program.
And that's what I get every time I run it even though I am using lock(this). Why lock(this) works well here?
class Program
{
static void Main(string[] args)
{
Test t = new Test();
for (int x = 0; x < 100; x++)
{
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++)
{
threads[i] = new Thread(t.ProtectedMethod);
threads[i].Start();
}
for (int i = 0; i < 10; i++)
threads[i].Join();
Console.WriteLine("Done with {0}", t.i);
}
}
}
class Test
{
public int i = 0;
public void ProtectedMethod()
{
lock (this)
{
i++;
}
}
}
The lock on this prevents multiple threads to enter the lock code block for the object at the same time. While one thread is in the code block, the other threads are waiting until the current lock on 'this' object is released.
It runs okay because example is too simple. It's equivalent to the case when you lock on some private variable. I say that it will even run fine if you wrap for loop with lock (t) since lock supports recursion.
But imagine if other thread had locked on your variable and entered some infinite loop? Just after you created variable? A deadlock would occur.
Now let's imagine you provide your code with lock (this) as 3rd party dll. You never know how smart will be the consumer of your library...

Categories