I'm making server-client application. Client can manage server files (rename/copy/delete etc.) When I select more than one like (n) files to copy/paste it starts (n) threads of pasteC
I need a way to make them in a queue. How do I do that???
private void Paste()
{
foreach (ListViewItem item in copiedItems)
{
Thread pasteC = new Thread(unused => fmc.PasteFromCopy(item.Text, somePath));
pasteC.Start();
}
}
the code down is in fmc class..
public void PasteFromCopy(string source,string dest)
{
if (IsFolder(source))
{
CopyDirectory(source, dest);
}
else
{
CopyStream(source, dest);
}
}
I think there is no reason to use threads here. You're just making your code more complicated and consume too much memory (each thread needs 1 MB of memory). Do something like this and you won't have to worry about queues or locks:
private void Paste()
{
foreach (ListViewItem item in copiedItems)
{
fmc.PasteFromCopy(item.Text, somePath);
}
}
EDIT:
If you need to use thread other than the main thread, because you don't want to lock that up, you can use one thread that does all the copying. Something like:
private void Paste()
{
var thread = new Thread(() =>
{
foreach (ListViewItem item in copiedItems)
{
fmc.PasteFromCopy(item.Text, somePath);
}
});
thread.Start();
}
Still no need to use locks, and much more memory efficient than your solution with many threads.
i've figured it out
public void PasteFromCopy(string source,string dest)
{
lock(this)
{
if (IsFolder(source))
{
CopyDirectory(source, dest);
}
else
{
CopyStream(source, dest);
}
}
}
Related
I have a list with hundreds items,
when I try to sort the items, it always blocking my program.
It' so too annoying.
I try to use Task.Run(), It doesn't work.
private void resultListView_ColumnClick(object sender, ColumnClickEventArgs e)
{
// doesn't work
Task.Run(() => ListViewOperate((ListView)sender, ListViewOP.SORT));
// doesn't work
resultListView.BeginUpdate();
ListViewOperate((ListView)sender, ListViewOP.SORT);
resultListView.EndUpdate();
}
private delegate void ListViewOperateDelegate(System.Windows.Forms.ListView liv,
ListViewOP op);
private void ListViewOperate(System.Windows.Forms.ListView liv, ListViewOP op)
{
if (liv.InvokeRequired)
{
var addDele = new ListViewOperateDelegate(ListViewOperate);
liv.Invoke(addDele, new object[] { liv, op});
}
else
{
if (op == ListViewOP.SORT)
{
liv.BeginUpdate();
liv.Sort();
liv.EndUpdate();
}
}
}
The trick you are trying to use, doesn't work here, because you are starting the
ListViewOperator on a thread/task but the callback checks if it is started on the UI thread. If it isn't on the UI thread, invoke it on the UI thread. So what benefits did you gain? none..
You should check the Virtual Mode. With the virtual mode you are able to sort it (a copy) of the list on a task/thread and then swap the list "variable" and trigger the listview to refresh it self.
Here is an Example
I'm working on a simple irc chat bot (specifically for twitch.tv streams), and I'm using a List to keep a list of all the users in the channel. When someone leaves or joins, I add or remove them from the list. Then I have a thread that runs every minute that checks if the stream is online, and if it is, it hands out "currency" to all the people in my user list.
I'm sure you can already see where my problem is. If someone leaves or joins while my program is looping through the users in my list, then I get a Collection Modified exception. Currently, as a workaround, I just make a temp list and copy the real list into it, then loop through the temp list instead, but I was just curious if there was a "better" way to do it?
Quick psuedocode:
private List<string> users = new List<string>();
private void IrcInitialize(){
//connect to irc stuff
//blah
//blah
//blah
Thread workThread = new Thread(new ThreadStart(doWork());
workThread.Start();
}
private void ircListener(){
parseIRCMessage(StreamReader.ReadLine());
}
private void parseIRCMessage(msg){
if (msgType == "JOIN"){
users.Add(user);
}
else if (msgType == "PART"){
users.Remove(user);
}
}
private void doWork(){
while (true) {
if (streamOnline() && handOutTime()){
handOutCurrency();
}
Thread.Sleep(60000);
}
}
private void handOutCurrency(){
List<string> temp = users; //This is what I'm currently doing
foreach (String user in temp) {
database.AddCurrency(user, 1);
}
}
Any other suggestions?
I suggest using a ConcurrentBag<string> for the users.
This allows multi-threaded access to the users even while it is being enumerated.
The big plus is that you do not have to worry about locking.
There are two ways to solve this problem:
Using a lock to synchronize access between two threads, or
Doing all access from a single thread.
The first way is simple: add lock(users) {...} block around the code that reads or modifies the users list.
The second way is slightly more involved: define two concurrent queues, toAdd and toRemove in your class. Instead of adding or removing users directly from the users list, add them to the toAdd and toRemove queues. When the sleeping thread wakes up, it should first empty both queues, performing the modifications as necessary. Only then it should hand out the currency.
ConcurrentQueue<string> toAdd = new ConcurrentQueue<string>();
ConcurrentQueue<string> toRemove = new ConcurrentQueue<string>();
private void parseIRCMessage(msg){
if (msgType == "JOIN"){
toAdd.Enqueue(user);
}
else if (msgType == "PART"){
toRemove.Enqueue(user);
}
}
private void doWork(){
while (true) {
string user;
while (toAdd.TryDequeue(out user)) {
users.Add(user);
}
while (toRemove.TryDequeue(out user)) {
users.Remove(user);
}
if (streamOnline() && handOutTime()){
handOutCurrency();
}
Thread.Sleep(60000);
}
}
The suggestions from dasblinkenlight's answer are good. Another option is to do something similar to what you suggested: work with a immutable copy of the list. Except with normal List, you would need to make sure that it's not changed while you're copying it (and you would actually need to copy the list, not just a reference to it, like your code suggested).
A better version of this approach would be to use ImmutableList from the immutable collections library. With that, each modification creates a new collection (but sharing most parts with the previous version to improve efficiency). This way, you could have one thread that modifies the list (actually, creates new lists based on the old one) and you could also read the list from another thread at the same time. This will work, because new changes won't be reflected in an old copy of the list.
With that, your code would look something like this:
private ImmutableList<string> users = ImmutableList<string>.Empty;
private void ParseIRCMessage(string msg)
{
if (msgType == "JOIN")
{
users = users.Add(user);
}
else if (msgType == "PART")
{
users = users.Remove(user);
}
}
private void HandOutCurrency()
{
foreach (String user in users)
{
database.AddCurrency(user, 1);
}
}
You need to lock on the list during all reads, writes, and iterations of the list.
private void parseIRCMessage(msg){
lock(users)
{
if (msgType == "JOIN"){
users.Add(user);
}
else if (msgType == "PART"){
users.Remove(user);
}
}
}
private void doWork(){
while (true) {
if (streamOnline() && handOutTime()){
handOutCurrency();
}
Thread.Sleep(60000);
}
}
private void handOutCurrency(){
lock(users)
{
foreach (String user in users) {
database.AddCurrency(user, 1);
}
}
}
etc...
I have a class in C# like this:
public MyClass
{
public void Start() { ... }
public void Method_01() { ... }
public void Method_02() { ... }
public void Method_03() { ... }
}
When I call the "Start()" method, an external class start to work and will create many parallel threads that those parallel threads call the "Method_01()" and "Method_02()" form above class. after end of working of the external class, the "Method_03()" will be run in another parallel thread.
Threads of "Method_01()" or "Method_02()" are created before creation of thread of Method_03(), but there is no guaranty to end before start of thread of "Method_03()". I mean the "Method_01()" or the "Method_02()" will lost their CPU turn and the "Method_03" will get the CPU turn and will end completely.
In the "Start()" method I know the total number of threads that are supposed to create and run "Method_01" and "Method_02()". The question is that I'm searching for a way using semaphore or mutex to ensure that the first statement of "Method_03()" will be run exactly after end of all threads which are running "Method_01()" or "Method_02()".
Three options that come to mind are:
Keep an array of Thread instances and call Join on all of them from Method_03.
Use a single CountdownEvent instance and call Wait from Method_03.
Allocate one ManualResetEvent for each Method_01 or Method_02 call and call WaitHandle.WaitAll on all of them from Method_03 (this is not very scalable).
I prefer to use a CountdownEvent because it is a lot more versatile and is still super scalable.
public class MyClass
{
private CountdownEvent m_Finished = new CountdownEvent(0);
public void Start()
{
m_Finished.AddCount(); // Increment to indicate that this thread is active.
for (int i = 0; i < NUMBER_OF_THREADS; i++)
{
m_Finished.AddCount(); // Increment to indicate another active thread.
new Thread(Method_01).Start();
}
for (int i = 0; i < NUMBER_OF_THREADS; i++)
{
m_Finished.AddCount(); // Increment to indicate another active thread.
new Thread(Method_02).Start();
}
new Thread(Method_03).Start();
m_Finished.Signal(); // Signal to indicate that this thread is done.
}
private void Method_01()
{
try
{
// Add your logic here.
}
finally
{
m_Finished.Signal(); // Signal to indicate that this thread is done.
}
}
private void Method_02()
{
try
{
// Add your logic here.
}
finally
{
m_Finished.Signal(); // Signal to indicate that this thread is done.
}
}
private void Method_03()
{
m_Finished.Wait(); // Wait for all signals.
// Add your logic here.
}
}
This appears to be a perfect job for Tasks. Below I assume that Method01 and Method02 are allowed to run concurrently with no specific order of invocation or finishing (with no guarantee, just typed in out of memory without testing):
int cTaskNumber01 = 3, cTaskNumber02 = 5;
Task tMaster = new Task(() => {
for (int tI = 0; tI < cTaskNumber01; ++tI)
new Task(Method01, TaskCreationOptions.AttachedToParent).Start();
for (int tI = 0; tI < cTaskNumber02; ++tI)
new Task(Method02, TaskCreationOptions.AttachedToParent).Start();
});
// after master and its children are finished, Method03 is invoked
tMaster.ContinueWith(Method03);
// let it go...
tMaster.Start();
What it sounds like you need to do is to create a ManualResetEvent (initialized to unset) or some other WatHandle for each of Method_01 and Method_02, and then have Method_03's thread use WaitHandle.WaitAll on the set of handles.
Alternatively, if you can reference the Thread variables used to run Method_01 and Method_02, you could have Method_03's thread use Thread.Join to wait on both. This assumes however that those threads are actually terminated when they complete execution of Method_01 and Method_02- if they are not, you need to resort to the first solution I mention.
Why not use a static variable static volatile int threadRuns, which is initialized with the number threads Method_01 and Method_02 will be run.
Then you modify each of those two methods to decrement threadRuns just before exit:
...
lock(typeof(MyClass)) {
--threadRuns;
}
...
Then in the beginning of Method_03 you wait until threadRuns is 0 and then proceed:
while(threadRuns != 0)
Thread.Sleep(10);
Did I understand the quesiton correctly?
There is actually an alternative in the Barrier class that is new in .Net 4.0. This simplifies the how you can do the signalling across multiple threads.
You could do something like the following code, but this is mostly useful when synchronizing different processing threads.
public class Synchro
{
private Barrier _barrier;
public void Start(int numThreads)
{
_barrier = new Barrier((numThreads * 2)+1);
for (int i = 0; i < numThreads; i++)
{
new Thread(Method1).Start();
new Thread(Method2).Start();
}
new Thread(Method3).Start();
}
public void Method1()
{
//Do some work
_barrier.SignalAndWait();
}
public void Method2()
{
//Do some other work.
_barrier.SignalAndWait();
}
public void Method3()
{
_barrier.SignalAndWait();
//Do some other cleanup work.
}
}
I would also like to suggest that since your problem statement was quite abstract, that often actual problems that are solved using countdownevent are now better solved using the new Parallel or PLINQ capabilities. If you were actually processing a collection or something in your code, you might have something like the following.
public class Synchro
{
public void Start(List<someClass> collection)
{
new Thread(()=>Method3(collection));
}
public void Method1(someClass)
{
//Do some work.
}
public void Method2(someClass)
{
//Do some other work.
}
public void Method3(List<someClass> collection)
{
//Do your work on each item in Parrallel threads.
Parallel.ForEach(collection, x => { Method1(x); Method2(x); });
//Do some work on the total collection like sorting or whatever.
}
}
im sending smses using dll, that dll have some events one them is
Session_OnMessageAccepted
inside that im doing something like this
void Session_OnMessageAccepted(object sender,EventArgs e)
{
new Thread(
delegate()
{
//do stuff
}).Start();
}
this is ok only problem is the code inside dostuff gets excuted same time , is there is any chance i can put "dostuff"in a queue and make it happen synchronously?
You're looking for the ConcurrentQueue class.
You can add the messages in the queue. And you can have a separate thread started(On App Start) which will continuously look for messages in the queue and process it.
i.e in the thread method
while(true)
{
//check if the queue is empty otherwise continue;
//fetch the element
//process it
}
A Note About The ThreadPool
As a general comment to your current code, consider using ThreadPool.QueueUserWorkItem rather than creating new threads.
Queuing work items to the ThreadPool is much more efficient than creating new threads for short term tasks. The ThreadPool maintains a pool of existing threads and re-uses them. Creating and managing threads is expensive so should be avoided when needing many short-lived tasks. As well as being efficient, the ThreadPool also has natural queuing behaviour.
However, using the ThreadPool does not guarantee that items are executed in the order you queued them, and may also result in items being executated at the same time i.e. concurrently. Therefore the ThreadPool doesn't help you out for this particular quesiton.
Example Message Processing Loop
The following is a message processing loop pattern which allows operations to be queued and then processing on a separate thread serially.
public class SomeClass
{
private readonly object _syncObj = new object();
private readonly Thread _thread;
private readonly Queue<Action> _queue = new Queue<Action>();
private readonly ManualResetEvent _messageAccepted = new ManualResetEvent(false);
public SomeClass()
{
_thread = new Thread(() =>
{
while (true)
{
Action operation;
while (TryDequeue(out operation))
{
operation();
}
_messageAccepted.WaitOne();
}
}) {IsBackground = true};
_thread.Start();
}
private void Session_OnMessageAccepted(object sender, EventArgs e)
{
Action operation = () =>{/* Do stuff */};
Enqueue(operation);
}
private void Enqueue(Action operation)
{
lock (_syncObj)
{
_queue.Enqueue(operation);
_messageAccepted.Set();
}
}
private bool TryDequeue(out Action operation)
{
lock (_syncObj)
{
operation = (_queue.Count != 0) ? _queue.Dequeue() : null;
if (operation == null) _messageAccepted.Reset();
return (operation != null);
}
}
}
I'm starting with the C# code example here. I'm trying to adapt it for a couple reasons: 1) in my scenario, all tasks will be put in the queue up-front before consumers will start, and 2) I wanted to abstract the worker into a separate class instead of having raw Thread members within the WorkerQueue class.
My queue doesn't seem to dispose of itself though, it just hangs, and when I break in Visual Studio it's stuck on the _th.Join() line for WorkerThread #1. Also, is there a better way to organize this? Something about exposing the WaitOne() and Join() methods seems wrong, but I couldn't think of an appropriate way to let the WorkerThread interact with the queue.
Also, an aside - if I call q.Start(#) at the top of the using block, only some of the threads every kick in (e.g. threads 1, 2, and 8 process every task). Why is this? Is it a race condition of some sort, or am I doing something wrong?
using System;
using System.Collections.Generic;
using System.Text;
using System.Messaging;
using System.Threading;
using System.Linq;
namespace QueueTest
{
class Program
{
static void Main(string[] args)
{
using (WorkQueue q = new WorkQueue())
{
q.Finished += new Action(delegate { Console.WriteLine("All jobs finished"); });
Random r = new Random();
foreach (int i in Enumerable.Range(1, 10))
q.Enqueue(r.Next(100, 500));
Console.WriteLine("All jobs queued");
q.Start(8);
}
}
}
class WorkQueue : IDisposable
{
private Queue<int> _jobs = new Queue<int>();
private int _job_count;
private EventWaitHandle _wh = new AutoResetEvent(false);
private object _lock = new object();
private List<WorkerThread> _th;
public event Action Finished;
public WorkQueue()
{
}
public void Start(int num_threads)
{
_job_count = _jobs.Count;
_th = new List<WorkerThread>(num_threads);
foreach (int i in Enumerable.Range(1, num_threads))
{
_th.Add(new WorkerThread(i, this));
_th[_th.Count - 1].JobFinished += new Action<int>(WorkQueue_JobFinished);
}
}
void WorkQueue_JobFinished(int obj)
{
lock (_lock)
{
_job_count--;
if (_job_count == 0 && Finished != null)
Finished();
}
}
public void Enqueue(int job)
{
lock (_lock)
_jobs.Enqueue(job);
_wh.Set();
}
public void Dispose()
{
Enqueue(Int32.MinValue);
_th.ForEach(th => th.Join());
_wh.Close();
}
public int GetNextJob()
{
lock (_lock)
{
if (_jobs.Count > 0)
return _jobs.Dequeue();
else
return Int32.MinValue;
}
}
public void WaitOne()
{
_wh.WaitOne();
}
}
class WorkerThread
{
private Thread _th;
private WorkQueue _q;
private int _i;
public event Action<int> JobFinished;
public WorkerThread(int i, WorkQueue q)
{
_i = i;
_q = q;
_th = new Thread(DoWork);
_th.Start();
}
public void Join()
{
_th.Join();
}
private void DoWork()
{
while (true)
{
int job = _q.GetNextJob();
if (job != Int32.MinValue)
{
Console.WriteLine("Thread {0} Got job {1}", _i, job);
Thread.Sleep(job * 10); // in reality would to actual work here
if (JobFinished != null)
JobFinished(job);
}
else
{
Console.WriteLine("Thread {0} no job available", _i);
_q.WaitOne();
}
}
}
}
}
The worker threads are all blocking on the _q.WaitOne() call in DoWork(). Calling the thread's Join() method will deadlock, the threads never exit. You'll need to add a mechanism to signal to worker thread to exit. A ManualResetEvent, tested with WaitAny in the worker, will get the job done.
One debugging tip: get familiar with the Debug + Windows + Threads window. It lets you switch between threads and look at their call stacks. You'd have quickly found this problem by yourself.
You do a WaitOne() at the end of DoWork but you never set it after the threads start running.
Note that AutoResetEvent will go back to not set state after a 'successful' WaitOne
Your loop in your DoWork method never finishes. This will cause the thread to always be busy and this thread.Join() will block forever, waiting for it to complete.
You have a WaitOne, but I don't think it's necessary unless there is a reason you want your threadpool to stick around after your work is complete:
private void DoWork()
{
bool done = false;
while (!done)
{
int job = _q.GetNextJob();
if (job != Int32.MinValue)
{
Console.WriteLine("Thread {0} Got job {1}", _i, job);
Thread.Sleep(job * 10); // in reality would to actual work here
if (JobFinished != null)
JobFinished(job);
}
else
{
Console.WriteLine("Thread {0} no job available", _i);
done = true;
}
}
}
If you want the threads to stick around so you don't have to realloc more threads when WorkQueue.Start is called, you'd have to do something more elaborate with the AutoResetEvent.
Your main problem is the deterministic deadlock described in the other answers.
The correct way to handle it, though, is not to fix the deadlock, but to eliminate the Event altogether.
The whole idea of the Producer-Consumer model is that the clients En-queue and De-queue elements concurrently, and that's why sync mechanisms are required. If you're enqueuing all of the elements beforehand and then only dequeue concurrently, you only need a lock on the dequeue, since the "Event" is used to let "Consumers" wait for new elements to be enqueued; this will not happen in your case (based on your description).
Also, the "single responsibility" design principle suggests that the threading code should be separated from the "Blocking Queue" code. Make the "Blocking Queue" a class of its own, then use it in your thread-management class.