Reputation: 2333
In my C# WPF application, I am doing certain async reporting work using BackgroundWorker. I am able to update the UI from backgroundWorker using ProgressChanged event.
But, I need to ask for user inputs during the process, at certain points in background process I need to open window asking for user's input, depending on that input the background process will further continue.
Can I open some window from background process and then continue the process after user has responded on that window ?
Upvotes: 0
Views: 902
Reputation: 159
You basically have 2 options:
Here is an example which can be used to prompt an indefinite number of prompts and continue the job afterwards.
//You can bind this to a Button or any other WPF event,
// the point is that it should be run from UI thread
private async void JobStartEvent()
{
JobResult jobResult = new JobResult
{
JobStatus = JobStatus.NotStarted
};
while (jobResult.JobStatus != JobStatus.Done)
{
jobResult = await DoLongJob(jobResult.ContinuationInfo);
if (jobResult.JobStatus == JobStatus.UserPromptRequired)
{
jobResult.ContinuationInfo.PromptResult = PromptAndGetResult(jobResult.PromptInfo);
}
}
}
private async Task<JobResult> DoLongJob(JobContinuationInfo continuationInfo)
{
//Do long stuff here
// continue the job using "continuationInfo"
//When prompt needed, Do:
{
return new JobResult
{
JobStatus = JobStatus.UserPromptRequired,
PromptInfo = new PromptInfo(), //Fill with information required for prompt
ContinuationInfo = new ContinuationInfo() //Fill with information required for continuing the job (can be a delegate to a local function to continue the job)
};
}
//When done, Do:
{
return new JobResult { JobStatus = JobStatus.Done};
}
}
private async JobResult DoLongJob()
{
return JobResult =
}
private enum JobStatus
{
NotStarted,
UserPromptRequired,
Done
}
internal class JobContinuationInfo
{
public PromptResult PromptResult { get; set; }
// Other properties to continue the job
}
private class JobResult
{
public JobStatus JobStatus { get; set; }
public PromptInfo PromptInfo { get; set; }
public JobContinuationInfo ContinuationInfo { get; set; }
}
Read More: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/
System.Windows.Threading.Dispatcher.Invoke<ResultType>(async () =>
{
return PromptUserAndGetResult();
});
Read More: https://learn.microsoft.com/en-us/dotnet/api/system.windows.threading.dispatcher.invoke
Upvotes: 0
Reputation: 1583
You should split it up into different background workers. When you get to a point in your process that requires user input, finish/complete your background worker and then collect the input on the UI thread and then kick off the next worker with the input.
I would recommend using the Task / async / await methodology for this instead of a background worker. It will make this kind of process far easier to write and also understand:
private void async RunTheJob()
{
// Run Part1 async and wait for the result
var result1 = await Part1();
// Now collect your UI input based on result1
var uiInput = ......;
// Run Part2 async and wait for the result
var result2 = await Part2(uiInput);
}
private Task<Part1ReturnObjectTypeHere> Part1()
{
Part1ReturnObjectTypeHere result = null;
...do async work here to populate result...
return result;
}
Upvotes: 1