C# 等待工作不正常

C# 等待工作不正常,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我正在尝试为我们的一个程序编写一个窗口管理器。它应该向客户端显示一系列窗口,每个窗口要求不同的信息,然后在移动到下一个窗口之前处理这些信息。可以动态添加或删除新窗口,从而启用窗口管理器。为了做到这一点,我有一个提供父窗口的主shell。每个子窗口都作为内容插入到父窗口中。单击“下一步”按钮时,孩子应该处理屏幕上的信息,然后让家长知道它可以移动到下一个窗口。由于某些窗口的处理时间可能长达30秒,因此我希望在处理过程中显示忙碌指示灯。我通过在我的父视图上使用Telerik RadBusyIndica

我正在尝试为我们的一个程序编写一个窗口管理器。它应该向客户端显示一系列窗口,每个窗口要求不同的信息,然后在移动到下一个窗口之前处理这些信息。可以动态添加或删除新窗口,从而启用窗口管理器。为了做到这一点,我有一个提供父窗口的主shell。每个子窗口都作为内容插入到父窗口中。单击“下一步”按钮时,孩子应该处理屏幕上的信息,然后让家长知道它可以移动到下一个窗口。由于某些窗口的处理时间可能长达30秒,因此我希望在处理过程中显示忙碌指示灯。我通过在我的父视图上使用Telerik RadBusyIndicator来实现这一点。为了正确显示忙碌指示器,我尝试使用wait/async异步调用OnNext方法。正在调用OnNext方法并正在进行处理,但在处理过程中UI线程被锁定,并且未显示忙碌指示器。我的代码的相关部分如下:

ShellViewModel.cs(父窗口的视图模型):

SetupWindowManager.cs:

    public async Task<bool?> OnNext()
    {
                    //calls into the current view model to begin processing
        bool? retVal = CurrentViewModel.OnNext();

        if (retVal == true)
            CurrentViewCounter++;

        return retVal;
    }

            //Called from GetCurrentView to set the current view model and perform any initialization that view model might need
    public async Task<SetupViewInit> InitializeView()
    {

        CurrentView = currentViewList[CurrentViewCounter];
        CurrentViewModel.FireNextAction += FireNextAction;
        CurrentViewModel.PropertyChanged += PropertyChanged;
        SetupViewInit retVal = CurrentViewModel.Init();

        if (retVal == SetupViewInit.NextScreen)
        {
            CurrentViewCounter++;
            retVal = await InitializeView();
        }
        else if (retVal == SetupViewInit.TypeChange)
        {
            SetupType = SetupApp.Config.SetupType;
            MachineType = SetupApp.Config.MachineType;
            GetViewList();
            retVal = await InitializeView();
        }

        return retVal;
    }
public异步任务OnNext()
{
//调用当前视图模型以开始处理
bool?retVal=CurrentViewModel.OnNext();
如果(retVal==true)
CurrentViewCounter++;
返回返回;
}
//从GetCurrentView调用以设置当前视图模型并执行视图模型可能需要的任何初始化
公共异步任务InitializeView()
{
CurrentView=currentViewList[CurrentViewCounter];
CurrentViewModel.FireNextAction+=FireNextAction;
CurrentViewModel.PropertyChanged+=PropertyChanged;
SetupViewInit retVal=CurrentViewModel.Init();
if(retVal==SetupViewInit.NextScreen)
{
CurrentViewCounter++;
retVal=wait InitializeView();
}
else if(retVal==SetupViewInit.TypeChange)
{
SetupType=SetupApp.Config.SetupType;
MachineType=SetupApp.Config.MachineType;
GetViewList();
retVal=wait InitializeView();
}
返回返回;
}
同样,所有代码都正确执行。代码只是锁定了UI线程。如果有什么不同的话,我正在使用.NET4.0中的Bcl编译器组件。这是一个大项目,我们还没有准备好迁移到.NET4.5

编辑:我对Sethcran的回答的回应太长,无法发表评论

我无法使用Task.Run,因为我们尚未使用.Net 4.5库。然而,这让我开始关注Task.Factory.StartNew。我更改了我的代码,如下所示,并遇到了评论中指出的问题:

        Task.Factory.StartNew<SetupViewInit>(new Func<SetupViewInit>(async () =>
        {
            CurrentView = currentViewList[CurrentViewCounter];
            CurrentViewModel.FireNextAction += FireNextAction;
            CurrentViewModel.PropertyChanged += PropertyChanged;
            SetupViewInit retVal = CurrentViewModel.Init();

            if (retVal == SetupViewInit.NextScreen)
            {
                CurrentViewCounter++;
                retVal = await InitializeView();
            }
            else if (retVal == SetupViewInit.TypeChange)
            {
                SetupType = SetupApp.Config.SetupType;
                MachineType = SetupApp.Config.MachineType;
                GetViewList();
                retVal = await InitializeView();
            }
                            //On the following line, VS shows an "Unexpected return value" error
            return retVal;

        }));
Task.Factory.StartNew(新函数(异步()=>
{
CurrentView=currentViewList[CurrentViewCounter];
CurrentViewModel.FireNextAction+=FireNextAction;
CurrentViewModel.PropertyChanged+=PropertyChanged;
SetupViewInit retVal=CurrentViewModel.Init();
if(retVal==SetupViewInit.NextScreen)
{
CurrentViewCounter++;
retVal=wait InitializeView();
}
else if(retVal==SetupViewInit.TypeChange)
{
SetupType=SetupApp.Config.SetupType;
MachineType=SetupApp.Config.MachineType;
GetViewList();
retVal=wait InitializeView();
}
//在下一行中,VS显示“意外返回值”错误
返回返回;
}));
那么如何从任务中获取返回值呢


我无法让这两种方法中的任何一种起作用,结果走上了完全不同的道路。谢谢你的建议,但我实在没有时间再在这个项目上乱搞它们了。

使用wait和async关键字本身并不会使代码在以后异步运行。通过调用异步方法,它可以正常运行。唯一真正的区别是它的结果将作为任务对象返回。我怀疑,在您的情况下,由于我没有明确看到工作被分拆到另一个线程上或以其他方式排队等待以后,这个任务对象在您的处理方法返回之前不会返回,并且它已经标记为已完成,因此,这里的wait和async关键字实际上什么也没有做

考虑包装实际上希望在任务中异步运行的代码,通过

return Task.Run(() => { yourLongProcessingMethodsHere });
这将异步运行传入的代码,然后在当前线程上同时返回当前正在执行的显式任务对象

因此,简言之,async/await只会对那些明确编写用于处理它们的方法有好处,这些方法要么派生出自己的线程来完成工作,要么排队等待事件在以后运行,以标记任务完成


有关async/await的更多信息,请参阅:

使用await和async关键字本身并不会使代码随后异步运行。通过调用异步方法,它可以正常运行。唯一真正的区别是它的结果将作为任务对象返回。我怀疑,在您的情况下,由于我没有明确看到工作被分拆到另一个线程上或以其他方式排队等待以后,这个任务对象在您的处理方法返回之前不会返回,并且它已经标记为已完成,因此,这里的wait和async关键字实际上什么也没有做

考虑包装实际上希望在任务中异步运行的代码,通过

return Task.Run(() => { yourLongProcessingMethodsHere });
这将异步运行传入的代码,然后重试