I am adding messages to a threading channel and reading from this channel constantly. I noticed that if I do not add a Task.Delay
then all of the messages are not processed. The program will exit with maybe 10 messages processed when it should be 1000.
Adding a Task.Delay
after each write seems hacky. Is there a better way to read all messages in the channel without adding a Task.Delay
after each write?
Is there something wrong with my StartListener()
method?
internal class Program
{
static List<Task> taskList = new List<Task>();
private static Channel<string> messageList = Channel.CreateUnbounded<string>();
static int midpointCount = 0;
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
Task.WhenAll(Task.Run(() => StartListener()));
for (int i = 0; i < 10; i++)
{
int task = i;
taskList.Add(Task.Run(() => StartJob(task)));
}
Task.WaitAll(taskList.ToArray());
sw.Stop();
Console.WriteLine("Total Messages Processed: {0} in time {1} MessageListCount {2}", midpointCount, sw.Elapsed, messageList.Reader.Count);
}
private static async Task<string> StartListener()
{
var cancellationtoken = new CancellationTokenSource(TimeSpan.FromMinutes(60)).Token;
await foreach (var msg in messageList.Reader.ReadAllAsync(cancellationtoken))
{
if (!string.IsNullOrEmpty(msg))
{
Console.WriteLine(msg);
Interlocked.Increment(ref midpointCount);
}
}
return "Finished";
}
private static async Task<string> StartJob(int TaskNum)
{
Random rnd = new Random();
for (int i = 0; i < 100; i++)
{
var cancellationtoken = new CancellationTokenSource(TimeSpan.FromMinutes(60)).Token;
try
{
var message = string.Format("TaskNum {0} Message added #{1}", TaskNum, rnd.Next(1, 3000));
await messageList.Writer.WriteAsync(message);
await Task.Delay(50); //<--- Here it seems it will only read all messages with a delay involved.
}
catch (OperationCanceledException)
{
// ignored
}
}
return "Finished";
}
}
Task.WhenAll(Task.Run(() => StartListener()));
StartListener
returns a Task
. You wrap that in Task.Run
, starting another thread to run that task. You then pass than task to the Task.WhenAll
method , which returns a Task
that you promptly throw away.
The only tasks you add to the taskList
variable are the StartJob
tasks. Your Main
method will finish as soon as all of the StartJob
tasks have finished. It will not wait for the StartListener
task to finish.
Change your code to wait for the listener to finish.
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
taskList.Add(Task.Run(() => StartListener()));
for (int i = 0; i < 10; i++)
{
int task = i;
taskList.Add(Task.Run(() => StartJob(task)));
}
Task.WaitAll(taskList.ToArray());
sw.Stop();
Console.WriteLine("Total Messages Processed: {0} in time {1} MessageListCount {2}",
midpointCount, sw.Elapsed, messageList.Reader.Count);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.