This is the C# Code
app.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
app.MapSignalR(hubConfiguration);
CpuEngine cpuEngine = new CpuEngine(1500);
MemoryEngine memoryEngine = new MemoryEngine(1500);
// Task.Factory.StartNew(async () => await cpuEngine.StartCpuCheck());
// Task.Factory.StartNew(async () => await memoryEngine.StartCheckMemory());
Only the first one is running. How can I run each other?
1) Use Task.Run instead.
2) Remove the keywords async and await in the lambda.
3) Use Task.WhenAll and pass in the two tasks.
public async Task InvokeAsync()
{
var cpuEngine = new CpuEngine(1500);
var memoryEngine = new MemoryEngine(1500);
await Task.WhenAll(
Task.Run(() => cpuEngine.StartCpuCheck()),
Task.Run(() => memoryEngine.StartCheckMemory()));
}
Related
I am trying to use asynchronous programming with async and await to calculate some values and save in a database periodically using ASP.NET Core 2.x. The method shown below is not executing from the thread pool.
public async void CalculateCIndex(int CIndexId)
{
List<string> UserIds = _context.ApplicationUsers
.Where(m => m.EmailConfirmed == true)
.Select(m => m.Id).ToList();
for (int i = 0; i < UserIds.Count; i += 10)
{
var temp = UserIds.Skip(i).Take(10);
foreach (var Id in temp)
{
await Task.Run(async () =>
{
await CIndexCal(Id, CIndexId);
});
}
await Task.Delay(6000);
}
}
public async Task CIndexCal(string Id, int CIndexId)
{
_context.CIndexMember.Add(new CIndexMember
{
NCIndex = (decimal)((AindexAfterRar + Power) / CI.TotalCindex)
});
_context.SaveChanges();
}
You can find good answer here:
async/await - when to return a Task vs void?
Your method CIndexCal is declared as async but it is not async at all due to fact you are not using async methods inside. In order to change this you could change:
_context.SaveChanges();
to
await _context.SaveChangesAsync();
Then instead of:
await Task.Run(async () =>
{
await CIndexCal(Id, CIndexId);
});
you just need:
await CIndexCal(Id, CIndexId);
and I am not sure why you are making delay and I think you don't need this:
await Task.Delay(6000);
I have three tasks like this
public List<CheckResponse> Check(CheckRequest request)
{
var Responses = new List<CheckResponse>();
List<Task> TaskList = new List<Task>();
Task task1 = new Task(() =>
{
Service gatewayObject = new Service();
var response = gatewayObject.Check();
Responses.Add(response);
});
task1.Start();
TaskList.Add(task1);
Task task2 = new Task(() =>
{
Service gatewayObject = new Service();
var response = gatewayObject.Check();
Responses.Add(response);
});
task2.Start();
TaskList.Add(task2);
Task task3 = new Task(() =>
{
Service gatewayObject = new Service();
var response = gatewayObject.Check();
Responses.Add(response);
});
task3.Start();
TaskList.Add(task3);
Task.WaitAll(TaskList.ToArray());
return Responses;
}
Each of them make request to service and can return positive result
so I want to cancel other two task if any of them return positive result.
Service side code is not accessible for me so I can not make any changes on service side.
I have a series of Tasks that I want to run in order from a-z.
I would like to execute these calls synchronously starting from 1 and ending at N.
task1 DeleteSubProjects...1
task1 DeleteActivities...2
task1 DeleteActivityPersons...3
task2 DeleteThreads...4
task1 DeleteCommunicationThreadContentTags...5
task2 DeleteCommunicationThreadParticipants...6
task3 DeleteMessages
task4 Delete(communicationThread)
task3 DeleteActivityDocuments
task4 DeleteActivityNotes
task5 DeleteActivityMachines
task6 DeleteActivityLinks
task7 DeleteActivityLinks
task8 Delete(activity)
task2 DeleteSubProjectDocuments
task3 DeleteSubProjectNotes
task4 DeleteSubProjectPersons
task5 DeleteSubProjects
task6 Delete(subProject)
task2 deleteProjectNotes
task3 deleteProjectDocuments
task4 deleteActivities
task5 deleteProjectPersons
here is what the code looks like
public async Task DeleteProject(Project project)
{
var deleteSubProjects = UnitOfWork.Instance.SubProjectService.DeleteSubProjects(project.SubProjects);
var deleteProjectNotes = UnitOfWork.Instance.ProjectNoteService.DeleteProjectNotes(project.ProjectNotes);
var deleteProjectDocuments = UnitOfWork.Instance.ProjectDocumentService.DeleteProjectDocuments(project.ProjectDocuments);
var deleteActivities = UnitOfWork.Instance.ActivityService.DeleteActivities(project.Activities);
var deleteProjectPersons = UnitOfWork.Instance.ProjectPersonService.DeleteProjectPersons(project.ProjectPersons);
await Task.WhenAll(deleteSubProjects)
.ContinueWith(_ => deleteProjectNotes)
.ContinueWith(_ => deleteProjectDocuments)
.ContinueWith(_ => deleteActivities)
.ContinueWith(_ => deleteProjectPersons)
.ContinueWith(_ => Delete(project)).Unwrap();
}
subprojects
public async Task DeleteSubProjects(IList<SubProject> subProjects)
{
foreach (var subProject in subProjects.ToList())
{
await DeleteSubProject(subProject);
}
}
public async Task DeleteSubProject(SubProject subProject)
{
var task1 = UnitOfWork.Instance.ActivityService.DeleteActivities(subProject.Activities);
var task2 = UnitOfWork.Instance.SubProjectDocumentService.DeleteSubProjectDocuments(subProject.SubProjectDocuments);
var task3 = UnitOfWork.Instance.SubProjectNoteService.DeleteSubProjectNotes(subProject.SubProjectNotes);
var task4 = UnitOfWork.Instance.SubProjectPersonService.DeleteSubProjectPersons(subProject.SubProjectPersons);
var task5 = DeleteSubProjects(subProject.ChildSubProjects);
var task6 = Delete(subProject);
await Task.WhenAll(task1)
.ContinueWith(_ => task2)
.ContinueWith(_ => task3)
.ContinueWith(_ => task4)
.ContinueWith(_ => task5)
.ContinueWith(_ => task6).Unwrap();
//Delete(subProject);
}
activities
public async Task DeleteActivities(IList<Activity> activities)
{
foreach (var activity in activities)
{
await DeleteActivity(activity);
}
}
public async Task DeleteActivity(Activity activity)
{
var task1 = UnitOfWork.Instance.ActivityPersonService.DeleteActivityPersons(activity.ActivityPersons);
var task2 = UnitOfWork.Instance.CommunicationThreadService.DeleteThreads(activity.CommunicationThreads);
var task3 = UnitOfWork.Instance.ActivityDocumentService.DeleteActivityDocuments(activity.ActivityDocuments);
var task4 = UnitOfWork.Instance.ActivityNoteService.DeleteActivityNotes(activity.ActivityNotes);
var task5 = UnitOfWork.Instance.ActivityMachineService.DeleteActivityMachines(activity.ActivityMachines);
var task6 = UnitOfWork.Instance.ActivityLinkService.DeleteActivityLinks(activity.SuccActivityLinks);
var task7 = UnitOfWork.Instance.ActivityLinkService.DeleteActivityLinks(activity.PredActivityLinks);
var task8 = Delete(activity);
await Task.WhenAll(task1)
.ContinueWith(_ => task2)
.ContinueWith(_ => task3)
.ContinueWith(_ => task4)
.ContinueWith(_ => task5)
.ContinueWith(_ => task6)
.ContinueWith(_ => task7)
.ContinueWith(_ => task8).Unwrap();
// Delete(activity);
}
threads
internal async Task DeleteThreads(IList<CommunicationThread> threads)
{
foreach (var thread in threads)
{
await DeleteThread(thread);
}
}
internal async Task DeleteThread(CommunicationThread communicationThread)
{
var task1 = UnitOfWork.Instance.CommunicationThreadContentTagService.DeleteCommunicationThreadContentTags(communicationThread.CommunicationThreadContentTags);
var task2 = UnitOfWork.Instance.CommunicationThreadParticipantService.DeleteCommunicationThreadParticipants(communicationThread.CommunicationThreadParticipants);
var task3 = UnitOfWork.Instance.CommunicationMessageService.DeleteMessages(communicationThread.CommunicationMessages.Where(msg => msg.CommentOnMessageID == null).ToList());
var task4 = Delete(communicationThread);
await Task.WhenAll(task1)
.ContinueWith(_ => task2)
.ContinueWith(_ => task3)
.ContinueWith(_ => task4).Unwrap();
}
Rather than calling Task.WhenAll and declaring a variable for each Task, simply await each one in the order you need -- for example:
public async Task DeleteProject(Project project)
{
var instance = UnitOfWork.Instance;
await instance.SubProjectService.DeleteSubProjects(project.SubProjects);
await instance.ProjectNoteService.DeleteProjectNotes(project.ProjectNotes);
await instance.ProjectDocumentService.DeleteProjectDocuments(project.ProjectDocuments);
await instance.ActivityService.DeleteActivities(project.Activities);
await instance.ProjectPersonService.DeleteProjectPersons(project.ProjectPersons);
}
Now the order of the delete operations in this specific example are serialized.
I am starting 2 channels in the mediaservices azure portal.
Starting a channel takes a long time to complete, about 25-30 seconds per channel. Hence, multithreading :)
However, the following is not clear to me:
I have 2 methods:
public async Task<bool> StartAsync(string programName, CancellationToken token = default(CancellationToken))
{
var workerThreads = new List<Thread>();
var results = new List<bool>();
foreach (var azureProgram in _accounts.GetPrograms(programName))
{
var thread = new Thread(() =>
{
var result = StartChannelAsync(azureProgram).Result;
lock (results)
{
results.Add(result);
}
});
workerThreads.Add(thread);
thread.Start();
}
foreach (var thread in workerThreads)
{
thread.Join();
}
return results.All(r => r);
}
and
private async Task<bool> StartChannelAsync(IProgram azureProgram)
{
var state = _channelFactory.ConvertToState(azureProgram.Channel.State);
if (state == State.Running)
{
return true;
}
if (state.IsTransitioning())
{
return false;
}
await azureProgram.Channel.StartAsync();
return true;
}
in the first method I use
var result = StartChannelAsync(azureProgram).Result;
In this case everything works fine. But if I use
var result = await StartChannelAsync(azureProgram);
Executing is not awaited and my results has zero entries.
What am I missing here?
And is this a correct way?
Any comments on the code is appreciated. I am not a multithreading king ;)
Cheers!
Don't span new Thread instances to execute tasks in parallel, instead use Task.WhenAll:
public async Task<bool> StartAsync(string programName, CancellationToken token = default(CancellationToken))
{
// Create a task for each program and fire them "at the same time"
Task<bool>[] startingChannels = _accounts.GetPrograms(programName))
.Select(n => StartChannelAsync(n))
.ToArray();
// Create a task that will be completed when all the supplied tasks are done
bool[] results = await Task.WhenAll(startingChannels);
return results.All(r => r);
}
Note: I see that you're passing a CancellationToken to your StartAsync method, but you're not actually using it. Consider passing it as an argument to StartChannelAsync, and then use it when calling azureProgram.Channel.StartAsync
If you love one-liners:
public async Task<bool> StartAsync(string programName, CancellationToken token = default(CancellationToken))
{
return (await Task.WhenAll(_accounts.GetPrograms(programName)
.Select(p => StartChannelAsync(p))
.ToArray())).All(r => r);
}
i was looking for way out run multiple task and report about task status not sequencially.
here i am pasting a code where multiple task running and reporting when all task complete.
var task1 = Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
return "dummy value 1";
});
var task2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(13000);
return "dummy value 2";
});
var task3 = Task.Factory.StartNew(() =>
{
Thread.Sleep(2000);
return "dummy value 3";
});
Task.Factory.ContinueWhenAll(new[] { task1, task2, task3 }, tasks =>
{
foreach (Task<string> task in tasks)
{
Console.WriteLine(task.Result);
}
});
Console.ReadLine();
task1 will take less time and then task3 will complete and last task2 will complete but ContinueWhenAll always showing task1 is completed and then task2 & task3. i want to modify the code in such way as a result which task complete fast that will show first not sequentially. where to change in code. guide please. thanks
UPDATE
var taskp = Task.Factory.StartNew(() =>
{
var task1 = Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
return "Task1 finished";
}).ContinueWith((continuation) => { Console.WriteLine(continuation.Result); });
var task2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(3000);
return "Task2 finished";
}).ContinueWith((continuation) => { Console.WriteLine(continuation.Result); });
var task3 = Task.Factory.StartNew(() =>
{
Thread.Sleep(2000);
return "Task3 finished";
}).ContinueWith((continuation) => { Console.WriteLine(continuation.Result); });
return "Main Task finished";
});
taskp.ContinueWith(t => Console.WriteLine(t.Result));
Console.ReadLine();
An easy solution would be to ContinueWith each task, individually. This is a very quick and dirty example:
var taskp = Task.Factory.StartNew(() =>
{
var task1 = Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
return "dummy value 1";
}).ContinueWith((continuation) => { Console.WriteLine("task1"); });
var task2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(3000);
return "dummy value 2";
}).ContinueWith((continuation) => { Console.WriteLine("task2"); });
var task3 = Task.Factory.StartNew(() =>
{
Thread.Sleep(2000);
return "dummy value 3";
}).ContinueWith((continuation) => { Console.WriteLine("task3"); });
Task.Factory.ContinueWhenAll(new Task[] { task1, task2, task3}, (x) => { Console.WriteLine("Main Task Complete"); });
});
The code is updated to adapt to OP's UPDATE, with a "Main" task which will output after all the "inner" tasks are complete. To make it so taskp returns the string instead of writing it, the code becomes
var taskp = Task.Factory.StartNew<string>(() =>
{
var task1 = ...; //same
var task2 = ...; //same
var task3 = ...; //same
return "Main Task Complete";
}).ContinueWith((x)=> Console.WriteLine(x.Result));
The StartNew<> overload must be used to specify the return type for the Task to have a Result.