为了账号安全,请及时绑定邮箱和手机立即绑定

从后台进程打开窗口并在 WPF 中获取用户的输入

从后台进程打开窗口并在 WPF 中获取用户的输入

C#
精慕HU 2023-07-22 16:45:40
在我的 C# WPF 应用程序中,我使用 BackgroundWorker 执行某些异步报告工作。我可以使用 ProgressChanged 事件从 backgroundWorker 更新 UI。但是,我需要在此过程中请求用户输入,在后台进程的某些点上,我需要打开窗口询问用户输入,根据该输入,后台进程将进一步继续。我可以从后台进程打开某个窗口,然后在用户对该窗口做出响应后继续该过程吗?
查看完整描述

2 回答

?
aluckdog

TA贡献1847条经验 获得超7个赞

您应该将其分成不同的后台工作人员。当您的流程到达需要用户输入的点时,完成/完成您的后台工作程序,然后收集 UI 线程上的输入,然后使用该输入启动下一个工作程序。


我建议使用任务/异步/等待方法来代替后台工作人员。这将使这种过程更容易编写和理解:


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;

}


查看完整回答
反对 回复 2023-07-22
?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

你基本上有两个选择:

  1. (最佳实践)正如其他人所指出的,最佳实践是使用 async/await 链来异步完成工作,而不是后台工作人员。您只需将所有后台作业代码放入异步方法中并使用await 关键字调用它即可。

下面是一个示例,可用于提示无限数量的提示并随后继续作业。

    //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; }

    }


了解更多: https: //learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/


要使用后台工作程序,您可以使用 Dispatcher.Invoke 方法并将窗口创建代码传递到那里。窗口创建将在 UI 线程中完成,但后台工作线程将等待它执行,获取结果(可以是提示的结果),然后继续执行。

    System.Windows.Threading.Dispatcher.Invoke<ResultType>(async () =>

    {

        return PromptUserAndGetResult();

    });

查看完整回答
反对 回复 2023-07-22
  • 2 回答
  • 0 关注
  • 145 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信