Google 프로그램 중 하나에 대한 창 관리자를 작성하려고합니다. 각 창에서 다른 정보를 묻고 다음 창으로 이동하기 전에 해당 정보를 처리하는 일련의 창을 클라이언트에 표시해야합니다. 새 창을 동적으로 추가하거나 제거 할 수 있으므로 창 관리자가됩니다. 이렇게하기 위해 부모 창을 제공하는 메인 셸이 있습니다. 각 하위 창이 부모 창에 내용으로 삽입됩니다. 다음 버튼을 클릭하면 화면 정보를 처리 한 다음 부모에게 다음 창으로 이동할 수 있음을 알립니다. 일부 Windows에서는 처리 시간이 최대 30 초까지 걸릴 수 있으므로이 처리가 진행되는 동안 사용 중 표시기를 표시하려고합니다. 부모보기에서 Telerik RadBusyIndicator를 사용하여이를 수행하고 있습니다. 통화 중 표시기를 제대로 표시하기 위해 await/async를 사용하여 OnNext 메서드를 비동기 적으로 호출하려고합니다. OnNext 메서드가 호출되고 처리가 진행 중이지만 처리 중에 UI 스레드가 잠겨 있고 사용 표시기가 표시되지 않습니다.이 제대로 작동하지 않을 것입니다.
ShellViewModel.cs (부모 윈도우의 뷰 모델) :
protected async void NextAction()
{
//This is the property that is bound to the RadBusyIndicator to indicate if it should show or not
IsBusy = true;
//windowManager is the class that tells the child window to start processing and provides the parent window with the next view
bool? retVal = await windowManager.OnNext();
if (retVal == true)
{
GetCurrentView();
}
else if (retVal == null)
{
SetupApp.IsRestarting = true;
GetCurrentView();
SetupApp.Config.RestartPoint = windowManager.CurrentViewCounter;
File.WriteAllText("Config.xml", SetupConfig.Serialize(SetupApp.Config));
System.Diagnostics.Process.Start(Application.ResourceAssembly.Location);
Application.Current.Shutdown();
}
IsBusy = false;
}
private async void GetCurrentView()
{
IsBusy = true;
SetupViewInit retVal = await windowManager.InitializeView();
if (retVal == SetupViewInit.CloseApp)
{
RaiseCloseRequest();
IsBusy = false;
return;
}
IsBusy = false;
Content = windowManager.CurrentView as FrameworkElement;
OnPropertyChanged("CanNext");
OnPropertyChanged("CanBack");
OnPropertyChanged("NextToolTip");
if (windowManager.IsFinalView)
{
CancelText = "Close";
SetupApp.IsComplete = true;
}
}
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;
}
의 전부를 다음과 같이 내 코드의 관련 부분은 코드가 제대로 실행되고 있습니다. 코드는 UI 스레드를 잠그고 있습니다. 어떤 차이가 있다면, .net 4.0에서 Bcl 컴파일러 구성 요소를 사용하고 있습니다. 큰 프로젝트이며 .net 4.5로 이동할 준비가되지 않았습니다.
편집 : Sethcran의 답변에 대한 내 답변이 너무 길어서 의견이 분분 할 것입니다.
아직 .Net 4.5 라이브러리를 사용하고 있지 않기 때문에 Task.Run을 사용할 수 없습니다. 하지만, 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;
}));
그래서 작업에서 반환 값을 얻으려면 어떻게해야합니까?
나는이 방법들 중 하나를 작동시키지 못하고 완전히 다른 경로로 가게되었다. 제안 해 주셔서 감사합니다. 그러나이 프로젝트에서 더 이상 그들과 어울리지 못하게 할 시간이 없습니다.
당신이 OnNext' 동 기적으로 실행 '을 알리는받을 컴파일러 경고를 무시하지 마십시오. 또한,'async void'를 피하십시오. –
작업에서 비동기 메서드를 호출 중이므로 작업 자체가 작업을 반환하는지 확인하십시오. 특히, Func이 Func 일 필요가 있다고 생각합니다. > –
Sethcran