This question already has answers here:
How to wait for async method to complete?
(7 answers)
Closed 2 years ago.
Let's say I have a MyThread class in my Windows C# app like this:
public class MyThread
{
Thread TheThread;
public MyThread()
{
TheThread = new Thread(MyFunc);
}
public void StartIfNecessary()
{
if (!TheThread.IsAlive)
TheThread.Start();
}
private void MyFunc()
{
for (;;)
{
if (ThereIsStuffToDo)
DoSomeStuff();
}
}
}
That works fine. But now I realize I can make my thread more efficient by using async/await:
public class MyThread
{
Thread TheThread;
public MyThread()
{
TheThread = new Thread(MyFunc);
}
public void StartIfNecessary()
{
if (!TheThread.IsAlive)
TheThread.Start();
}
private async void MyFunc()
{
for (;;)
{
DoSomeStuff();
await MoreStuffIsReady();
}
}
}
What I see now, is that the second time I call StartIfNecessary(), TheThread.IsAlive is false (and ThreadState is Stopped BTW) so it calls TheThread.Start() which then throws the ThreadStateException "Thread is running or terminated; it cannot restart". But I can see that DoMoreStuff() is still getting called, so the function is in fact still executing.
I suspect what is happening, is that when my thread hits the "await", the thread I created is stopped, and when the await on MoreStuffIsReady() completes, a thread from the thread pool is assigned to execute DoSomeStuff(). So it is technically true that the thread I created has been stopped, but the function I created that thread to process is still running.
So how can I tell if "MyFunc" is still active?
I can think of 3 ways to solve this:
1) Add a "bool IsRunning" which is set to true right before calling TheThread.Start(), and MyFunc() sets to false when it completes. This is simple, but requires me to wrap everything in a try/catch/finally which isn't awful but I was hoping there was a way to have the operating system or framework help me out here just in case "MyFunc" dies in some way I wasn't expecting.
2) Find some new function somewhere in System.Threading that will give me the information I need.
3) Rethink the whole thing - since my thread only sticks around for a few milliseconds, is there a way to accomplish this same functionality without creating a thread at all (outside of the thread pool)? Start "MyFunc" as a Task somehow?
Best practices in this case?
Sticking with a Plain Old Thread and using BlockingCollection to avoid a tight loop:
class MyThread
{
private Thread worker = new Thread(MyFunc);
private BlockingCollection<Action> stuff = new BlockingCollection<Action>();
public MyThread()
{
worker.Start();
}
void MyFunc()
{
foreach (var todo in stuff.GetConsumingEnumerable())
{
try
{
todo();
}
catch(Exception ex)
{
// Something went wrong in todo()
}
}
stuff.Dispose(); // should be disposed!
}
public void Shutdown()
{
stuff.CompleteAdding(); // No more adding, but will continue to serve until empty.
}
public void Add( Action stuffTodo )
{
stuff.Add(stuffTodo); // Will throw after Shutdown is called
}
}
BlockingCollection also shows examples with Task if you prefer to go down that road.
Rethink the whole thing
This is definitely the best option. Get rid of the thread completely.
It seems like you have a "consumer" kind of scenario, and you need a consumer with a buffer of data items to work on.
One option is to use ActionBlock<T> from TPL Dataflow:
public class NeedsADifferentName
{
ActionBlock<MyDataType> _block;
public NeedsADifferentName() => _block = new ActionBlock<MyDataType>(MyFunc);
public void QueueData(MyDataType data) => _block.Post(data);
private void MyFunc(MyDataType data)
{
DoSomeStuff(data);
}
}
Alternatively, you can build your own pipeline using something like Channels.
Related
Executing multithreaded methods make garbage. Why is that and can we prevent it?
ThreadPool.QueueUserWorkItem(callBack, state);
EDIT:
By garbage I mean objects that are created and then went out of scope. The garbage collection is very slow because of it's old version of mono. So every kb you save from the GC is a win. If you are not familiar with the unity engine, In the screenshot please see The GC column on the highlighted row. It says 0.6kb. Therefore it create 600 bytes of garbage. The callback code is not creating any garbage so this is rooted from ThreadPool.QueueUserWorkItem
EDIT 2: To elaborate further here is a more concrete example:
public class TestThread : MonoBehaviour
{
public void Update()
{
if (Time.frameCount%10 == 0)
ThreadPool.QueueUserWorkItem(DummyMethod);
}
public void DummyMethod(object meaningless)
{
}
}
Here is the result. Please look at the highlighted row. The GC column says 285Bytes. Since DummyMethod is not doing anything, the garbage is related to ThreadPool.
Edit 3:
To relax the situation and find an alternative, it would be acceptable to have a worker thread that executes jobs from a queue.
It would be OK But it MUST run on CPU other than the one unity uses if there are multiple CPUs available. Unity does nearly anything in a single thread so a background worker on the same CPU would be a disaster. Also it is a cross platform project so windows-only solutions won't work. So basically I need a worker thread solution and to know if it possible to realize if a thread's CPU is the same as another thread's.
When you ThreadPool.QueueUserWorkItem(DummyMethod); it actually is implicitly turning your code in to ThreadPool.QueueUserWorkItem(new WaitCallback(DummyMethod));, that callback may be the item that is getting put on to the GC. Try the following code to explicitly create the delegate and keep a reference to it and see if it reduces the amount of GCable data.
public class TestThread : MonoBehaviour
{
private readonly WaitCallback _callback;
public TestThread()
{
_callback = new WaitCallback(DummyMethod);
}
public void Update()
{
if (Time.frameCount%10 == 0)
ThreadPool.QueueUserWorkItem(_callback);
}
public void DummyMethod(object meaningless)
{
}
}
UPDATE: Here is a extremely basic implementation of a single threaded background worker, to give you a starting point. The below code is untested and may perform horribly, but it does give you an idea as a starting point.
public class BasicBackgroundWorker
{
private readonly Thread _backgroundWorkThread;
private readonly Queue<Action> _queue = new Queue<Action>();
private readonly ManualResetEvent _workAvailable = new ManualResetEvent(false);
public BasicBackgroundWorker()
{
_backgroundWorkThread = new Thread(BackgroundThread)
{
IsBackground = true,
Priority = ThreadPriority.BelowNormal,
Name = "BasicBackgroundWorker Thread"
};
_backgroundWorkThread.Start();
}
public void EnqueueWork(Action work)
{
lock (_queue)
{
_queue.Enqueue(work);
_workAvailable.Set();
}
}
private void BackgroundThread()
{
while (true)
{
_workAvailable.WaitOne();
Action workItem;
lock (_queue)
{
workItem = _queue.Dequeue();
if (_queue.Count == 0)
{
_workAvailable.Reset();
}
}
try
{
workItem();
}
catch (Exception ex)
{
//Log exception that happened in backgroundWork
}
}
}
}
I'm having problems with multi-threading in an application I'm working on at the minute.
The process basically involves a list of items which need to be processed. As part of this processing a call needs to be made to a 3rd party api which does not support multi threading.
I've attempted to introduce a singleton instance of the API class and use locking to ensure that only one thread makes a call to it at once but I still get a situation were one thread gets stuck on the call to the API and the others are then stuck waiting on the lock to be released.
If I pause the debug session and check the callstack for the threads the one that has made it to the API call has the following trace:
mscorlib.dll!System.Threading.WaitHandle.WaitAll(System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
mscorlib.dll!System.Threading.WaitHandle.WaitAll(System.Threading.WaitHandle[] waitHandles)
I've tested this on a single thread by swapping out the thread pool in the foreach loop with an explicit call to the Process method and it works fine (although slower than I would like, there is quite a lot of processing before and after the API call).
Am I doing something wrong here or is this an issue with the third party api?
public class MyClass
{
private static ThirdPartyApi ApiInstance;
private static object lockObject = new object();
...
public void DoWork(list)
{
...
foreach (var item in list)
{
ThreadPool.QueueUserWorkItem(Process, item);
}
...
}
public void Process(string item)
{
// Various processing
...
lock(lockObject)
{
var result = ApiInstance.Lookup(item);
}
...
}
Code that is thread unsafe doesn't necessarily mean that the methods are not re-entrant, some thread-unsafe libraries require all calls to come from the same thread, period. Try the following method using a BlockingCollection instead, which will issue all calls on the same thread and see if it resolves the issue.
public class MyClass<T>
{
private BlockingCollection<T> workQueue = new BlockingCollection<T>();
public MyClass()
{
Task.Factory.StartNew(ProcessWorkQueue, TaskCreationOptions.LongRunning);
}
public void DoWork(List<T> work)
{
foreach (var workItem in work)
{
workQueue.Add(workItem);
}
}
public void StopWork()
{
workQueue.CompleteAdding();
}
public void ProcessWorkQueue()
{
foreach(var item in workQueue.GetConsumingEnumerable())
{
//Do something here
}
}
}
Also, the ThreadPool is a shared resource and performing any blocking action on a Threadpool thread can exhaust it. Even if your code did work, it would need to be refactored to address this resource starvation issue.
Assume that we have some methods that do some big work.
Initially we don`t know how many methods there are ( can be 1 and can be 10 ).
In code this looks like this:
public interface IWorker
{
void DoWork(DataContainer data);
}
And several classes that implement this interface.
Then we have list of instances.
List<IWorker> workers = new List<IWorker>();
I want to run these methods asynchronously. In addition I want some callback when all of them are executed.
public void Callback()
{
Console.WriteLine("everything done");
}
Is there a way to do this without writing custom wrappers or so? With ThreadPool, Tasks, Parallel?
As I know Parrallel block thread untill tasks are completed so this is not a prefferd behaviour.
When creating Task there should be method without parameters as I`ve seen so this is not good as well.
In ThreadPool there is possibility to use method QueueUserWorkItem, but using this method I won`t get a single "total-completion" callback.
Of course, I can make my own wrapper that will implement the desired functionality using ThreadPool, but the goal is to make this without writing such one.
Can anyone help please?
Thanks.
You're looking for the TPL and the Task class.
Create a Task for each operation, then call Task.WhenAll to get an aggregate task
You're looking for Task.WhenAll. Create a bunch of Tasks that do what you want them to, then wait on all of the tasks and ContinueWith your callback. I split out an async version of the DoWork method - if you're always going to be calling it asynchronously you don't necessarily need to do that.
public interface IWorker
{
Task DoWorkAsync(string data);
void DoWork(string data);
}
public class Worker : IWorker
{
public Task DoWorkAsync(string data)
{
return Task.Run(() => DoWork(data));
}
public void DoWork(string data)
{
Console.WriteLine(data);
Thread.Sleep(100);
}
}
public class Runner
{
public void Callback()
{
Console.WriteLine("Everything done");
}
public void Run()
{
var workers = new List<IWorker> {new Worker(), new Worker(), new Worker()};
var tasks = workers.Select(t => t.DoWorkAsync("some data"));
Task.WhenAll(tasks).ContinueWith(task => Callback());
Console.WriteLine("Waiting");
}
}
Sounds like a prime candidate for the CountdownEvent class:
List<IWorker> workers = new List<IWorker>();
using (CountdownEvent e = new CountdownEvent(workers.Count))
{
foreach (IWorker worker in workers)
{
// Dynamically increment signal count.
e.AddCount();
// run work itself on another thread
ThreadPool.QueueUserWorkItem(delegate(object state)
{
try
{
((IWorker)state[0]).DoWork((DataContainer)state[1]);
}
finally
{
e.Signal();
}
},
// pass required parameters for block of work
new object[] { worker, dataForWorker });
}
// wait for all workers to finish
e.Wait();
// run callback code
}
I have a C# class that executes an infinite loop until a conditional variable is set to true. There's another class that waits for a network message and when the message is received there's a call to the other class to modify the conditional variable to true so it can exit the while loop. The waiting for the message is done in a separate thread:
The modifier class:
public class Modifier{
Otherclass log;
private static NetworkStream theStream;
private StreamReader theInput;
public Modifier(Otherclass other, NetworkStream str)
{
this.log = other;
theStream = str;
theInput = new StreamReader(theStream);
Thread listenThread = new Thread(new ThreadStart(listen));
listenThread.Start();
}
public void listen()
{
while (true)
{
log.postMessage(theInput.ReadLine());
}
}
}
And the other class:
public class Otherclass{
bool docontinue = true;
public void postMessage(string input)
{
docontinue = true;
}
public void wait()
{
while(!docontinue)
{
}
}
}
The problem is that the program gets stuck at the while(!docontinue) although a message is sent. I suspect that the problem is that the variable docontinue is not getting modified but I don't know if the problem is somewhere else.
There are various issues here -
The first, and direct answer to your question, is that you need to declare your boolean field using volatile:
private volatile bool doContinue = true;
That being said, having a loop that does a while loop with no body is very bad - it will use up 100% CPU on that thread, and just "spin" indefinitely.
A much better approach to situations like this is to replace your while loop with a WaitHandle, such as ManualResetEvent. This allows you to wait on the reset event, and block until you're ready to continue. You call Set() on it in the other thread to allow the execution to continue.
For example, try this:
public class Otherclass{
ManualResetEvent mre = new ManualResetEvent(false);
public void PostMessage(string input)
{
// Other stuff here...
mre.Set(); // Allow the "wait" to continue
}
public void Wait()
{
mre.WaitOne(); // Blocks until the set above
}
}
You have two (potentially) infinite loops here. And nothing actually ever calls Wait()
Is there a good reason why you need to waste cycles in a dummy loop inside the wait method? What purpose does it serve?
It seems to me, postMessage should kick off a new thread that will perform whatever work needs to get done after Wait() is supposed to break.
You can use Volatile
private volatile bool docontinue = true;
Try adding Thread.Sleep(100) in your cycle. Also consider using the ManualResetEvent class.
UPDATE: I've just checked, wait() exits even without Thread.Sleep, volatile and other things. But my test console app hangs because the listen() thead never ends...
Other people have pointed out that there are better ways to do this, but I wanted to point out an issue in the code you posted.
public class Otherclass{
bool docontinue = true;
public void postMessage(string input)
{
docontinue = true;
}
public void wait()
{
while(!docontinue)
{
}
}
}
docontinue doesn't change values. It starts as true and you set it to true when the message is posted. On top of that you have a not in your while clause, so the loop should never run as !docontinue is always false.
I have simple method in my C# app, it picks file from FTP server and parses it and stores the data in DB. I want it to be asynchronous, so that user perform other operations on App, once parsing is done he has to get message stating "Parsing is done".
I know it can achieved through asynchronous method call but I dont know how to do that can anybody help me please??
You need to use delegates and the BeginInvoke method that they contain to run another method asynchronously. A the end of the method being run by the delegate, you can notify the user. For example:
class MyClass
{
private delegate void SomeFunctionDelegate(int param1, bool param2);
private SomeFunctionDelegate sfd;
public MyClass()
{
sfd = new SomeFunctionDelegate(this.SomeFunction);
}
private void SomeFunction(int param1, bool param2)
{
// Do stuff
// Notify user
}
public void GetData()
{
// Do stuff
sfd.BeginInvoke(34, true, null, null);
}
}
Read up at http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx
try this method
public static void RunAsynchronously(Action method, Action callback) {
ThreadPool.QueueUserWorkItem(_ =>
{
try {
method();
}
catch (ThreadAbortException) { /* dont report on this */ }
catch (Exception ex) {
}
// note: this will not be called if the thread is aborted
if (callback!= null) callback();
});
}
Usage:
RunAsynchronously( () => { picks file from FTP server and parses it},
() => { Console.WriteLine("Parsing is done"); } );
Any time you're doing something asynchronous, you're using a separate thread, either a new thread, or one taken from the thread pool. This means that anything you do asynchronously has to be very careful about interactions with other threads.
One way to do that is to place the code for the async thread (call it thread "A") along with all of its data into another class (call it class "A"). Make sure that thread "A" only accesses data in class "A". If thread "A" only touches class "A", and no other thread touches class "A"'s data, then there's one less problem:
public class MainClass
{
private sealed class AsyncClass
{
private int _counter;
private readonly int _maxCount;
public AsyncClass(int maxCount) { _maxCount = maxCount; }
public void Run()
{
while (_counter++ < _maxCount) { Thread.Sleep(1); }
CompletionTime = DateTime.Now;
}
public DateTime CompletionTime { get; private set; }
}
private AsyncClass _asyncInstance;
public void StartAsync()
{
var asyncDoneTime = DateTime.MinValue;
_asyncInstance = new AsyncClass(10);
Action asyncAction = _asyncInstance.Run;
asyncAction.BeginInvoke(
ar =>
{
asyncAction.EndInvoke(ar);
asyncDoneTime = _asyncInstance.CompletionTime;
}, null);
Console.WriteLine("Async task ended at {0}", asyncDoneTime);
}
}
Notice that the only part of AsyncClass that's touched from the outside is its public interface, and the only part of that which is data is CompletionTime. Note that this is only touched after the asynchronous task is complete. This means that nothing else can interfere with the tasks inner workings, and it can't interfere with anything else.
Here are two links about threading in C#
Threading in C#
Multi-threading in .NET: Introduction and suggestions
I'd start to read about the BackgroundWorker class
In Asp.Net I use a lot of static methods for jobs to be done. If its simply a job where I need no response or status, I do something simple like below. As you can see I can choose to call either ResizeImages or ResizeImagesAsync depending if I want to wait for it to finish or not
Code explanation: I use http://imageresizing.net/ to resize/crop images and the method SaveBlobPng is to store the images to Azure (cloud) but since that is irrelevant for this demo I didn't include that code. Its a good example of time consuming tasks though
private delegate void ResizeImagesDelegate(string tempuri, Dictionary<string, string> versions);
private static void ResizeImagesAsync(string tempuri, Dictionary<string, string> versions)
{
ResizeImagesDelegate worker = new ResizeImagesDelegate(ResizeImages);
worker.BeginInvoke(tempuri, versions, deletetemp, null, null);
}
private static void ResizeImages(string tempuri, Dictionary<string, string> versions)
{
//the job, whatever it might be
foreach (var item in versions)
{
var image = ImageBuilder.Current.Build(tempuri, new ResizeSettings(item.Value));
SaveBlobPng(image, item.Key);
image.Dispose();
}
}
Or going for threading so you dont have to bother with Delegates
private static void ResizeImagesAsync(string tempuri, Dictionary<string, string> versions)
{
Thread t = new Thread (() => ResizeImages(tempuri, versions, null, null));
t.Start();
}
ThreadPool.QueueUserWorkItem is the quickest way to get a process running on a different thread.
Be aware that UI objects have "thread affinity" and cannot be accessed from any thread other than the one that created them.
So, in addition to checking out the ThreadPool (or using the asynchronous programming model via delegates), you need to check out Dispatchers (wpf) or InvokeRequired (winforms).
In the end you will have to use some sort of threading. The way it basically works is that you start a function with a new thread and it will run until the end of the function.
If you are using Windows Forms then a nice wrapper that they have for this is call the Background Worker. It allows you to work in the background with out locking up the UI form and even provides a way to communicate with the forms and provide progress update events.
Background Worker
.NET got new keyword async for asonchrynous functions. You can start digging at learn.microsoft.com (async). The shortest general howto make function asonchrynous is to change function F:
Object F(Object args)
{
...
return RESULT;
}
to something like this:
async Task<Object> FAsync(Object args)
{
...
await RESULT_FROM_PROMISE;
...
return RESULT;
}
The most important thing in above code is that when your code approach await keyword it return control to function that called FAsync and make other computation until promissed value has been returned and procede with rest of code in function FAsync.