class MultiThreading
{
public class ThreadClass
{
public string InputString { get; private set; }
public int StartPos { get; private set; }
public List<SearchAlgorithm.CandidateStr> completeModels;
public List<SearchAlgorithm.CandidateStr> partialModels;
public ThreadClass(string s, int sPos)
{
InputString = s;
StartPos = sPos;
completeModels = new List<SearchAlgorithm.CandidateStr>();
partialModels = new List<SearchAlgorithm.CandidateStr>();
}
public void Run(int strandID)
{
Thread t = new Thread(() => this._run(strandID));
t.Start();
}
private void _run(int strandID)
{
SearchAlgorithm.SearchInOneDirection(strandID, ref this.completeModels, ref this.partialModels);
}
public static void CombineResult(
List<ThreadClass> tc,
out List<SearchAlgorithm.CandidateStr> combinedCompleteModels,
out List<SearchAlgorithm.CandidateStr> combinedPartialModels)
{
// combine the result
}
}
}
class Program
{
static void Main(string s, int strandID)
{
int lenCutoff = 10000;
if (s.Length > lenCutoff)
{
var threads = new List<MultiThreading.ThreadClass>();
for (int i = 0; i <= s.Length; i += lenCutoff)
{
threads.Add(new MultiThreading.ThreadClass(s.Substring(i, lenCutoff), i));
threads[threads.Count - 1].Run(strandID);
}
**// How can I wait till all thread in threads list to finish?**
}
}
}
My question is how can I wait till all threads in "threads" list to finish and then do the call CombineResult method?
Thanks
You can add a List<Thread> structure to keep record of all your threads
private List<Thread> threads = new List<Thread>();
Then populate the list with the threads
public void Run(int strandID)
{
Thread t = new Thread(() => this._run(strandID));
t.Start();
threads.Add(t);
}
Lastly, you can have a method that calls Join for each thread in a list. It is usually a good practise to have a timeout delay so your program will not block forever (in case there is a bug in a thread)
public void WaitAll(List<Thread> threads, int maxWaitingTime)
{
foreach (var thread in threads)
{
thread.Join(maxWaitingTime); //throws after timeout expires
}
}
An alternative would be to use a Task class and to call Task.WaitAll
Have ThreadClass expose a means to join the thread:
private Thread nativeThread;
public void Run(int strandID)
{
nativeThread = new Thread(() => this._run(strandID));
nativeThread.Start();
}
public void Join()
{
nativeThread.Join();
}
And then use ThreadClass.Join on each thread after you start them:
var threads = new List<ThreadClass>();
for (int i = 0; i <= s.Length; i += lenCutoff)
{
threads.Add(new ThreadClass(s.Substring(i, lenCutoff), i));
threads[threads.Count - 1].Run(strandID);
}
// Waits for each thread to finish in succession
threads.ForEach(t => t.Join());
Or, throw away your ThreadClass and enjoy System.Threading.Tasks:
// e.g. class Models { Complete; Partial; }
// private Models Search(string source, int offset, int length, int ID)
var tasks = new List<Task<Models>>(
from x in Enumerable.Range(0, s.Length / lenCutoff)
select Task.Factory.StartNew<Models>(
() => Search(s, x, lenCutoff, strandID));
);
// private Models CombineResults(IEnumerable<Models> results)
var combine = Task.Factory.ContinueWhenAll<Models>(
tasks.ToArray(),
ts => CombineResults(ts.Select(t => t.Result)));
combine.Wait();
Models combinedModels = combine.Result;
Well I see the answer has already been chosen, but I had already started on writing a solution using System.Threading.Tasks as proposed by several others. Rather than using LINQ, I have tried to match the structure of the original code as much as possible:
class SearchClass
{
public String InputString { get; private set; }
public int StartPos { get; private set; }
public List<string> completeModels;
public List<string> partialModels;
public SearchClass(string s, int sPos)
{
InputString = s;
StartPos = sPos;
completeModels = new List<string>();
partialModels = new List<string>();
}
public void Run(int strandID)
{
// SearchAlgorithm.SearchInOneDirection(...);
}
// public static void CombineResult(...){ };
}
class Program
{
static void Main(string s, int strandID)
{
int lenCutoff = 10000;
if (s.Length > lenCutoff)
{
var searches = new List<SearchClass>();
var tasks = new List<System.Threading.Tasks.Task>();
for (int i = 0; i < s.Length; i += lenCutoff)
{
SearchClass newSearch = new SearchClass(s.Substring(i, lenCutoff), i);
searches.Add(newSearch);
tasks.Add(System.Threading.Tasks.Task.Factory.StartNew(()=>newSearch.Run(strandID)));
}
System.Threading.Tasks.Task.WaitAll(tasks.ToArray());
// Combine the result
}
}
}
Related
I have a class like this:
class Test {
const int capacity = 100_0000;
private HashSet<int> set = new HashSet<int>(capacity);
public Test() { this.Reassign(); }
private void Reassign() {
var thread = new Thread(() => {
while (true) {
set = new HashSet<int>(capacity);
Thread.Sleep(10);
}
});
thread.Start();
}
public void Add(int val) {
set.Add(val);
}
}
The add method is frequently called.
var test = new Test();
Task.Run(() => {
for (int i = 0; i < 100000000; i++) {
test.Add(i);
Thread.SpinWait(5000);
}
});
It doesn't matter whether the data is successfully stored in the set, in this case, is the behavior of the add method consistent with the following code?
class LockTest {
const int capacity = 100_0000;
private HashSet<int> set = new HashSet<int>(capacity);
public LockTest() { this.Reassign(); }
private void Reassign() {
var thread = new Thread(() => {
while (true) {
lock (set) set = new HashSet<int>(capacity);
Thread.Sleep(10);
}
});
thread.Start();
}
public void Add(int val) {
lock (set) set.Add(val);
}
}
In my tests, even if there is no lock statement, there is no error. But I don't know what happens at the moment of set = new HashSet<int>(capacity);.
If you change the code to this, what do you think will happen? My guess is that the number you print out will sometimes be the same and other time different. When it is the same, lock(set) has worked, but otherwise it hasn't.
class LockTest {
const int capacity = 100_0000;
private int setCnt = 0;
private object set = new object();
public LockTest() { this.Reassign(); }
private void Reassign() {
var thread = new Thread(() => {
while (true) {
lock (set) setCnt++;
Thread.Sleep(10);
}
});
thread.Start();
}
public void Add(int val) {
lock (set) Console.WriteLine($"{setCnt}");
}
}
I'm trying to run collection of tasks. I have a procesing object model, which properties I don't know. That's is why I've created a child of this class. I have a collection of ProcesingTask objects. This is my code:
public sealed class ProcessingTask : ProcessingObject
{
private CancellationTokenSource cancelToken;
private System.Timers.Timer _timer;
public int TimeOut {private get; set; }
public int ProcessObjectID { get; private set; }
public Task ProcessObjectTask { get; private set; }
public QueueObject queueObject { private get; set; }
public ProcessingTask(int processObjectID)
{
this.ProcessObjectID = processObjectID;
ResetTask();
}
private void InitialTimeOut()
{
_timer = new System.Timers.Timer(TimeOut);
_timer.Elapsed += new ElapsedEventHandler(TimedOut);
_timer.Enabled = true;
}
private void TimedOut(object sender, ElapsedEventArgs e)
{
cancelToken.Cancel();
Console.WriteLine("Thread {0} was timed out...", ProcessObjectID);
_timer.Stop();
}
public void ResetTask()
{
cancelToken = new CancellationTokenSource();
ProcessObjectTask = new Task(() => DoTaskWork(), cancelToken.Token);
}
public void DoTaskWork()
{
InitialTimeOut();
Random rand = new Random();
int operationTime = rand.Next(2000, 20000);
Thread.Sleep(operationTime);
_timer.Stop();
Console.WriteLine("Thread {0} was finished...", ProcessObjectID);
}
}
public class CustomThreadPool
{
private IList<ProcessingTask> _processingTasks;
public CustomThreadPool(List<ProcessingTask> processingObjects)
{
this._processingTasks = processingObjects;
}
public void RunThreadPool(Queue<QueueObject> queue, int batchSize)
{
for (int i = 1; i <= batchSize; i++)
{
QueueObject queueObject = queue.ToArray().ToList().FirstOrDefault();
ProcessingTask task = _processingTasks.FirstOrDefault(x => x.ProcessObjectID == queueObject.QueueObjectId);
task.queueObject = queue.Dequeue();
task.TimeOut = 3000;
task.ProcessObjectTask.Start();
}
}
public void WaitAll()
{
var tasks = _processingTasks.Select(x => x.ProcessObjectTask).ToArray();
Task.WaitAll(tasks);
}
}
I need to stop DoTaskWork() if running time was timed out. I'm trying to use timer and CancellationToken. But DoTaskWork() still doing his job after TimedOut(). Is any way to resolve this issue?
Though you send the cancel signal, you don't do anything with that in DoTaskWork
public void DoTaskWork()
{
InitialTimeOut();
Random rand = new Random();
int operationTime = rand.Next(2000, 20000);
// Thread.Sleep(operationTime); // this imitates a non-responsive operation
// but this imitates a responsive operation:
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
while (!cancelToken.IsCancellationRequested
&& stopwatch.ElapsedMilliseconds < operationTime)
{
Thread.Sleep(10);
}
_timer.Stop();
Console.WriteLine("Thread {0} was finished...", ProcessObjectID);
}
You have to implement your method DoTaskWork() accordingly.
Assume this as a sample. I am assuming that your thead is doing some continuos work rather just sleep. Otherwise you can use abort method which will just abort the thread even if its in sleep mode.
public void DoTaskWork()
{
InitialTimeOut();
Random rand = new Random();
int operationTime = rand.Next(2000, 20000);
while (true)
{
if (cancelToken.IsCancellationRequested)
{
throw new Exception("Cancellation requested.");
}
Thread.Sleep(operationTime);
}
_timer.Stop();
Console.WriteLine("Thread {0} was finished...", ProcessObjectID);
}
I would like to visualize how a queue when accessed by two reader threads and a writer thread grows and shrinks, with help of a progressbar in mainform. I will use a delegate to invoke the progress bar in main form and set its value to Queue.Value ( Toys.lenght). The progressbar does not behave as stated, it does not grow all the way and the lenght variables does not either.
public class Buffer
{
private delegate void Display(int v, ProgressBar f );
private Queue<Toy> Toys = new Queue<Toy>();
private object MyLock = new object();
private int max;
private int lenght;
private ProgressBar progressbar1;
public Buffer(ProgressBar r)
{
this.progressbar1 = r;
this.max = 10;
this.lenght = Toys.Count;
}
public void writeMethod(Toy toy)
{
lock (MyLock)
{
if (Toys.Count == max)
{
Monitor.Wait(MyLock);
}
Toys.Enqueue(toy);
Monitor.PulseAll(MyLock);
progressbar1.Invoke(new Display(Disp), new object[] {Toys.Count, progressbar1});
MessageBox.Show("Que contains these items" + lenght);
}
}
public void readMethod()
{
lock (MyLock)
{
if(Toys.Count == 0)
{
Monitor.Wait(MyLock);
}
Toys.Dequeue();
Monitor.PulseAll(MyLock);
}
}
public void Disp(int I, ProgressBar l)
{
progressbar1.Value = I;
}
}
}
Double check the variable lenght, use count instead. Change Progressbar default setting for maximum size from 100 to 10 to match size of the queue Toys. In Disp method change from = I to += I;
{
public class Buffer
{
private delegate void Display(int v, ProgressBar f );
private Queue<Toy> Toys = new Queue<Toy>();
private object MyLock = new object();
private int max;
private int lenght;
private ProgressBar progressbar1;
public Buffer(ProgressBar r)
{
this.progressbar1 = r;
this.max = 10;
this.lenght = Toys.Count;
}
public void writeMethod(Toy toy)
{
lock (MyLock)
{
if (Toys.Count >= max)
{
Monitor.Wait(MyLock);
}
if(Toys.Count <= max)
{
Toys.Enqueue(toy);
progressbar1.Invoke(new Display(Disp), new object[] {Toys.Count, progressbar1});
}
Monitor.PulseAll(MyLock);
MessageBox.Show("Que contains these items" + Toys.Count);
}
}
public void readMethod()
{
lock (MyLock)
{
if(Toys.Count == 0)
{
Monitor.Wait(MyLock);
}
Toys.Dequeue();
Monitor.PulseAll(MyLock);
}
}
public void Disp(int I, ProgressBar l)
{
progressbar1.Value += I;
}
}
}
have such code.
Start threads:
Thread[] thr;
static object locker = new object();
bool liking = true;
private void button2_Click(object sender, EventArgs e)
{
button2.Enabled = false;
button3.Enabled = true;
string post = create_note();
decimal value = Program.Data.numericUpDown1;
int i = 0;
int j = (int)(value);
thr = new Thread[j];
for (; i < j; i++)
{
thr[i] = new Thread(() => invite(post));
thr[i].IsBackground = true;
thr[i].Start();
}
}
public void invite(string post)
{
while (liking)
{
if (//some comdition)
exit all threads, and start string post = create_note(); again
}
}
If some condition in invite(string post) comes true I need to stop all threads, and go to string post = create_note(); again, get string post and start threads again.
How to do it?
Instead of manual thread management, use Parallel.For with CancellationToken:
var cts = new CancellationTokenSource();
var options = new ParallelOptions
{
CancellationToken = cts.Token,
MaxDegreeOfParallelism = System.Environment.ProcessorCount
};
var result = Parallel.For(0, j, options, i =>
{
invite(post);
options.CancellationToken.ThrowIfCancellationRequested();
});
When you want to cancel parallel calculations, just call cts.Cancel() from external code.
You can use lock and create a class that manage your threads like that :
public class SyncClass
{
public Thread[] thr;
private int NumberOfWorkingThreads { get; set; }
private object Sync = new object();
public int ThreadNumber { get; private set; }
public event EventHandler TasksFinished;
public SyncClass(int threadNumber)
{
thr = new Thread[threadNumber];
ThreadNumber = threadNumber;
NumberOfWorkingThreads = ThreadNumber;
//LunchThreads(threadNumber);
}
protected void OnTasksFinished()
{
if (TasksFinished == null)
return;
lock (Sync)
{
NumberOfWorkingThreads--;
if (NumberOfWorkingThreads == 0)
TasksFinished(this, new EventArgs());
}
}
public void LunchThreads()
{
string post = create_note();
for (int i = 0; i < ThreadNumber; i++)
{
thr[i] = new Thread(() => invite(post));
thr[i].IsBackground = true;
thr[i].Start();
}
}
private void invite(string post)
{
while (true)
{
if (true)
{
break;
}
}
OnTasksFinished();
}
}
Use the event to notify the end of all threads then the class will be used like that:
private void Operation()
{
var sync = new SyncClass(10);
sync.TasksFinished += sync_TasksFinished;
sync.LunchThreads();
}
void sync_TasksFinished(object sender, EventArgs e)
{
Operation();
}
I'm testing a class that wraps BackgroundWorker to perform an operation away from the UI thread in my application.
The test below fails if Timeout is exceeded and passes if progressEventCount reaches the expected number of events before then.
My question is about synchronization. asyncExecutor.Progressed is fired from the Thread Pool thread that BackgroundWorker is using and the test thread reads it back in the while loop.
Am I using lock correctly?
[Test]
[Timeout(1250)]
public void Execute()
{
var locker = new object();
const int numberOfEvents = 10;
const int frequencyOfEvents = 100;
var start = DateTime.Now;
int progressEventCount = 0;
IGradualOperation tester = new TestGradualOperation(numberOfEvents, frequencyOfEvents);
var asyncExecutor = new AsynchronousOperationExecutor();
asyncExecutor.Progressed += (s, e) => { lock (locker) progressEventCount++; };
asyncExecutor.Execute(tester);
while (true)
{
int count;
lock (locker)
{
count = progressEventCount;
}
if (count < numberOfEvents) continue;
Assert.Pass("Succeeded after {0} milliseconds", (DateTime.Now - start).TotalMilliseconds);
}
}
// Implementation
public class AsynchronousOperationExecutor
{
public void Execute(IGradualOperation gradualOperation)
{
var backgroundWorker = new BackgroundWorker {WorkerReportsProgress = true};
backgroundWorker.DoWork += BackgroundWorkerDoWork;
backgroundWorker.ProgressChanged += BackgroundWorkerProgressChanged;
backgroundWorker.RunWorkerAsync(gradualOperation);
}
private void BackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
var myArgs = e.UserState as ProgressEventArgs;
OnProgressed(myArgs);
}
static void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
var workerThis = sender as BackgroundWorker;
var operation = e.Argument as IGradualOperation;
if (workerThis == null || operation == null) return;
operation.Progressed += (s, e1) => workerThis.ReportProgress((int)e1.Percentage, e1);
operation.Run();
}
private void OnProgressed(ProgressEventArgs e)
{
if (Progressed != null)
Progressed(this, e);
}
public event EventHandler<ProgressEventArgs> Progressed;
}
// Test Helper Class
public class TestGradualOperation : IGradualOperation
{
private readonly int _numberOfEvents;
private readonly int _frequencyMilliseconds;
public TestGradualOperation(int numberOfEvents, int frequencyMilliseconds)
{
_numberOfEvents = numberOfEvents;
_frequencyMilliseconds = frequencyMilliseconds;
}
public void Run()
{
for (int i = 0; i < _numberOfEvents; i++)
{
Thread.Sleep(_frequencyMilliseconds);
OnProgressed(new ProgressEventArgs(i, _numberOfEvents));
}
}
private void OnProgressed(ProgressEventArgs e)
{
if (Progressed != null)
Progressed(this, e);
}
public event EventHandler<ProgressEventArgs> Progressed;
}
I think this revision is an improvement, blocking the test thread and signalling with an AutoResetEvent. Not winning any brownie points for test readability though.
[Test]
[Timeout(1250)]
public void Execute()
{
var locker = new object();
EventWaitHandle waitHandle = new AutoResetEvent(false);// <--
const int numberOfEvents = 10;
const int frequencyOfEvents = 100;
var start = DateTime.Now;
int progressEventCount = 0;
IGradualOperation tester = new TestGradualOperation(numberOfEvents, frequencyOfEvents);
var asyncExecutor = new AsynchronousOperationExecutor();
asyncExecutor.Progressed += (s, e) =>
{
lock (locker)
{
progressEventCount++;
waitHandle.Set();// <--
}
};
asyncExecutor.Execute(tester);
while (true)
{
waitHandle.WaitOne();// <--
if (progressEventCount < numberOfEvents) continue;
Assert.Pass("Succeeded after {0} milliseconds", (DateTime.Now - start).TotalMilliseconds);
}
}