C# Waiting for multiple threads to finish
List<Thread> threads = new List<Thread>();
foreach (cpsComms.cpsSerial ser in availPorts)
{
Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev));
t.Start((object)ser);//start thread and pass it the port
threads.Add(t);
}
foreach(var thread in threads)
{
thread.Join();
}
Edit
I was looking back at this, and I like the following better
availPorts.Select(ser =>
{
Thread thread = new Thread(lookForValidDev);
thread.Start(ser);
return thread;
}).ToList().ForEach(t => t.Join());
C# Wait Till All Threads Complete Execution
Slightly improved by using a thread-safe collection (.NET 4.0 compatible):
List<Task> taskList = new List<Task>();
ConcurrentBag<object> allObjectAttributes = new ConcurrentBag<object>();
taskList.Add(Task.Factory.StartNew(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Folder))));
taskList.Add(Task.Factory.StartNew(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.XMLFile))));
taskList.Add(Task.Factory.StartNew(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.TextFile))));
taskList.Add(Task.Factory.StartNew(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Parent))));
Task.WaitAll(taskList.ToArray());
return allObjectAttributes;
Alternative approach: use Task.Result
once all tasks have completed (thread-safe collection no longer required as only one thread modifies ArrayList
):
Task<object>[] taskList = {
Task.Factory.StartNew(() => (object)GetObjectAttributes(TreeViewAttrs.Folder)),
Task.Factory.StartNew(() => (object)GetObjectAttributes(TreeViewAttrs.XMLFile)),
Task.Factory.StartNew(() => (object)GetObjectAttributes(TreeViewAttrs.TextFile)),
Task.Factory.StartNew(() => (object)GetObjectAttributes(TreeViewAttrs.Parent))
};
Task.WaitAll(taskList);
ArrayList allObjectAttributes = new ArrayList();
foreach (Task<object> task in taskList) {
allObjectAttributes.Add(task.Result);
}
return allObjectAttributes;
Significantly improved by using Task.WhenAll
(.NET 4.5 only):
object[] allObjectAttributes = await Task.WhenAll(
Task.Run(() => GetObjectAttributes(TreeViewAttrs.Folder)),
Task.Run(() => GetObjectAttributes(TreeViewAttrs.XMLFile)),
Task.Run(() => GetObjectAttributes(TreeViewAttrs.TextFile)),
Task.Run(() => GetObjectAttributes(TreeViewAttrs.Parent))
);
return allObjectAttributes;
*Note: I used object
as the generic parameter as you left the return type of GetObjectAttributes
unspecified.
C# wait for all threads to finish in Main()
Perhaps Thread.Join() is what you're looking for?
you also might find this article usefull.
Create multiple threads and wait for all of them to complete
It depends which version of the .NET Framework you are using. .NET 4.0 made thread management a whole lot easier using Tasks:
class Program
{
static void Main(string[] args)
{
Task task1 = Task.Factory.StartNew(() => doStuff());
Task task2 = Task.Factory.StartNew(() => doStuff());
Task task3 = Task.Factory.StartNew(() => doStuff());
Task.WaitAll(task1, task2, task3);
Console.WriteLine("All threads complete");
}
static void doStuff()
{
//do stuff here
}
}
In previous versions of .NET you could use the BackgroundWorker
object, use ThreadPool.QueueUserWorkItem()
, or create your threads manually and use Thread.Join()
to wait for them to complete:
static void Main(string[] args)
{
Thread t1 = new Thread(doStuff);
t1.Start();
Thread t2 = new Thread(doStuff);
t2.Start();
Thread t3 = new Thread(doStuff);
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine("All threads complete");
}
C# .Net Wait for all threads to complete and get return values
Try using a Task<string>
instead of a Task
and querying the Task<string>.Result
Waiting for threads to complete
DISCLAIMER: I posted this answer only because it does what the OP asked for and I didn't take the answer from Servy: there's nothing that you can do. But I advice to NOT use this in a production environment. Personally I would ditch that library and implement it myself.
This said, as a test I created a class library that holds a method DoWork
which starts a background thread that runs for 10 seconds:
public class ThirdParty
{
public static void DoWork()
{
new Thread(() => Thread.Sleep(10000)) { IsBackground = true }.Start();
}
}
Now, the idea is to compare the running threads before and after the ThirdParty.DoWork
call. After the call, one (or more) thread-id's will be collected and translated into thread handle(s) by using OpenThread
. At the end, you can call WaitForMultipleObjects
to wait until the third party background thread has finished doing its work.
class Program
{
[DllImport("kernel32.dll")]
static extern uint WaitForMultipleObjects(int nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds);
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, int dwThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
const uint SYNCHRONIZE = 0x00100000;
static IntPtr GetThreadHandleById(int threadId)
{
return OpenThread(SYNCHRONIZE, false, threadId);
}
static void Main(string[] args)
{
var threads = new List<int>();
foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
threads.Add(thread.Id);
ThirdParty.DoWork();
var threadHandlesToWaitFor = new List<IntPtr>();
foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
if (!threads.Contains(thread.Id))
threadHandlesToWaitFor.Add(GetThreadHandleById(thread.Id));
Console.WriteLine("Waiting for {0} thread(s) to finish...", threadHandlesToWaitFor.Count);
WaitForMultipleObjects(threadHandlesToWaitFor.Count, threadHandlesToWaitFor.ToArray(), true, 0xffffffff);
foreach (var handle in threadHandlesToWaitFor)
CloseHandle(handle);
}
}
In essence, we're waiting for an unmanaged thread that seems to run the spawned managed thread. This can break in the future because .NET does not guarantee that every managed thread runs on its own unmanaged thread.
Wait multiple threads for one result
Finally I ended with the following solution:
private class RequestHandler
{
private EventWaitHandle _handle;
public RequestHandler(Func<string> request)
{
_handle = new EventWaitHandle(false, EventResetMode.ManualReset);
Start(request);
}
private void Start(Func<string> doRequest)
{
Result = doRequest();
_handle.Set();
}
public void WaitForResponse()
{
_handle.WaitOne();
}
public string Result { get; private set; }
}
private Object _lockObject = new Object();
private Dictionary<string, RequestHandler> _pendingRequests = new Dictionary<string, RequestHandler>();
public string GetCustomer(int id)
{
RequestHandler request;
lock (_lockObject)
{
if (!_pendingRequests.TryGetValue(id, out request))
{
request = new RequestHandler(() => LoadEntity(id));
_pendingRequests[id] = request;
}
}
request.WaitForResponse();
lock (_lockObject)
{
_pendingRequests.Clear();
}
return request.Result;
}
Although it is still possible to have duplicated posts to the server this is a very minimal chance (on thread deletes all the pending requests after the first thread created a request and before a second thread tries to get the same customer data).
Thanks to the inspiration the posts here gave.
C# Wait for signals from all the threads before proceed
Your code is prone to race conditions. After all threads have completed the first iteration, all events are still set; if a single thread then runs through the loop before the others get to reset their events, it'll see the other events still set, and stop waiting early.
There's plenty of ways to resolve this bug, but the best solution for you is System.Threading.Barrier
(also see Threading objects and features with section about Barrier). It's explicitly designed for this situation, where you want multiple threads to work in parallel through a multi-step algorithm.
Related Topics
Why C# Won't Allow Field Initializer with Non-Static Fields
How Should You Diagnose the Error Sehexception - External Component Has Thrown an Exception
How to Put Text on Progressbar
How to Add the Same Column to All Entities in Ef Core
Get Application's Window Handles
Wpf Combobox: Different Template in Textbox and Drop-Downlist
Programmatic Way to Get All the Available Languages (In Satellite Assemblies)
Which Checkedlistbox Event Triggers After a Item Is Checked
How Does C# Choose with Ambiguity and Params
Sorting an Array of Folder Names Like Windows Explorer (Numerically and Alphabetically) - Vb.Net
Getting Date or Time Only from a Datetime Object
Webdriver How to Wait Until the Element Is Clickable in Webdriver C#
Equivalent Code of Createobject in C#
Outofmemoryexception When I Read 500Mb Filestream
Static and Instance Methods with the Same Name
Why Is Parallel.Foreach Much Faster Then Asparallel().Forall() Even Though Msdn Suggests Otherwise