I wrote a thread test application to see multiple and parallel started threads returning behaviour. I am new on async programming so can you please give a comment about this code?
I create multiple instances of TestThreadClass
using Parallel to see what is happening when async operation is completed at the same time. When threads completed, I added them into a thread-safe dictionary (ConcurrentDictionary
) with their random generated guids.
Below is a random async class returns in 1 milliseconds;
public class TestThreadClass
{
private Task<ThreadResultModel> myTask;
public readonly int myNumber;
public readonly string myId;
public TestThreadClass(int _myNumber)
{
myNumber = _myNumber;
myId = Guid.NewGuid().ToString();
}
public async Task<ThreadResultModel> StartOperation()
{
myTask = InvokeOperation();
return await myTask;
}
private async Task<ThreadResultModel> InvokeOperation()
{
await Task.Delay(TimeSpan.FromMilliseconds(1));
return new ThreadResultModel(myNumber, myId, "Returned");
}
}
Below is creator class I used WinForms application. I start parallel threads and after they completed I fill them to a GridView
to compare return milliseconds;
public partial class Form1 : Form
{
private const int threadNumber = 100;
private readonly ConcurrentDictionary<string, ThreadResultModel> startedConcurrentDictionary;
private readonly ConcurrentDictionary<string, ThreadResultModel> returnedConcurrentDictionary;
public Form1()
{
InitializeComponent();
startedConcurrentDictionary = new ConcurrentDictionary<string, ThreadResultModel>();
returnedConcurrentDictionary = new ConcurrentDictionary<string, ThreadResultModel>();
}
private void Form1_Load(object sender, EventArgs e)
{
FillComboboxes();
}
private void FillComboboxes()
{
for (int i = 1; i <= threadNumber; i )
{
DdlThreadNumber.Items.Add(i.ToString());
}
}
private void BtnStartThreads_Click(object sender, EventArgs e)
{
Parallel.For(0, int.Parse(DdlThreadNumber.Text), StartAThread);
}
private void StartAThread(int threadTag)
{
TestThreadClass t = new TestThreadClass(threadTag);
startedConcurrentDictionary.TryAdd(t.myId, new ThreadResultModel(threadTag, t.myId, "Started"));
t.StartOperation().ContinueWith(result =>
{
returnedConcurrentDictionary.TryAdd(result.Result.MyId, result.Result);
});
}
private void BtnReport_Click(object sender, EventArgs e)
{
foreach (var item in startedConcurrentDictionary)
{
GrdThreads.Rows.Add(item.Value.MyNumber, item.Value.MyId, item.Value.EventType, item.Value.Time);
}
foreach (var item in returnedConcurrentDictionary)
{
GrdThreads.Rows.Add(item.Value.MyNumber, item.Value.MyId, item.Value.EventType, item.Value.Time);
}
}
private void GrdThreads_SelectionChanged(object sender, EventArgs e)
{
statusLabel.Text = GrdThreads.SelectedRows.Count.ToString();
}
}
I just want to know is this approach is correct or not.
CodePudding user response:
I just want to know is this approach is correct or not.
The answer to this question depends on what you are trying to achieve. What the code above does is:
Parallel.For
executes several items at once, but not all. It runs 100 calls on underlying scheduler and the number of executions at once depends on number of CPU cores. But it won't start new threads for each call, just re-use existing ones- Each
StartAThread
doesn't start a thread. They are just run on Parallel.For scheduler's thread until theawait
. After that, they disappear from any thread and after some delay they are added toThreadPool
ThreadPool
executes the work afterawait
s, load-balancing the calls between its threads- Code in
ContinueWith
method is also added onThreadPool
So, by just using await
or Parallel.For
, you won't create 100 threads. Since creating threads is slow and each thread take much memory, all those features will use some internal mechanisms to re-use the existing threads, as you don't need more threads than CPU can handle
But you still create 100 concurrent Tasks, all split into several parts (with await
or ContinueWith
), run independently by ThreadPool
on several threads (usually about number of CPU cores/threads).
If you literally want to create 100 threads, you need to use new Thread(...)
call