2016-07-23 7 views
0

起動中に長時間実行される操作を実行する必要があるXamarin Formsアプリケーションがあります。シーケンスが進行するにつれて変化する単純なステータスメッセージを持つページを使用して、進行状況をユーザーに知らせたいと思います。Xamarinフォームでアプリケーションの起動中に進行状況を表示する方法

一連の操作は、非同期メソッドのセットとして実装されています。非同期メソッドは、UIを更新するコードも含む非同期コンテナメソッドにラップされています。ここでは単純化したバージョンです:シーケンスの実行が完了するまで、

private async Task DoStartupSequence() 
{ 
    SetStatusMessage("Step 1"); 
    await DoStep1(); 
    SetStatusMessage("Step 2"); 
    await DoStep2(); 
    SetStatusMessage("Step 3"); 
    await DoStep3(); 
    SetStatusMessage("Completed"); 
} 

しかし、関係なく、私はシーケンスを起動する方法の、UIは更新されません。

public App() 
{ 
    InitializeComponent(); 
    Task.Run(() => DoStartupSequence()).Wait(); 
} 

私もOnStartメソッド内から非同期シーケンスを起動しようとしている:で

protected override async void OnStart() 
{ 
    await DoStartupSequence(); 
} 

は私がAppコンストラクタ内から独自のスレッド上のシーケンスを実行しようとしていますWinFormsのアプリケーションでは、この問題はApplication.DoEventsを使って解決することができます(ただし、このアプローチには独自の問題があります)。いずれにしても、Xamarin Formsはこれをサポートしていないようです。

これは、その実装に標準パターンが必要であると私が想像するような共通の要件のようです。誰がそれが何であるか知っていますか?

多くのおかげで、

ティム

更新:@BraveHeartからの提案を受けて、私はさらに正常に動作していないかを示すために私のテストコードを簡素化することができています。

次のサンプルでは、​​2つの静的ページを参照しています。各ページには、ラベルのみが含まれています。第1ページは長時間のシーケンスの開始をアナウンスし、第2ページは完了を発表します。私の目標は、これらの2ページが最初と2番目の間に1秒の遅延でレンダリングされていることを確認することです。実際には、両方のページが一緒にレンダリングされるため、ページ1が表示されることはありません。

public App() 
{ 
    InitializeComponent(); 

    var navigationPage = new NavigationPage(); 

    MainPage = navigationPage; 

    navigationPage.Navigation.PushAsync(new TestPage1(), false).Wait(); 

    Task.Delay(1000).Wait(); 

    navigationPage.Navigation.PushAsync(new TestPage2(), false).Wait(); 
} 

答えて

2

UIの変更は、UIスレッドを介してのみ行う必要があります。私はそれだけでそのようなラベルか何かの内容を設定仮定SetStatusMessage()含む

public App() 
{ 
    InitializeComponent(); 
    Task.Run(() => DoStartupSequence()).Wait(); 
} 

ここでのコードのこの作品は、DoStartupSequenceを(実行するために、別のタスク(スレッド)を作成するように指示します)はありませんには他に待っているものがあります。

だから私は、これはあなたの問題を解決するだろうと思います。この

public App() 
{ 
    InitializeComponent(); 
    StartupSequence(); 
} 

private async void StartupSequence() 
{ 
    SetStatusMessage("Step 1"); 
    await DoStep1(); 
    SetStatusMessage("Step 2"); 
    await DoStep2(); 
    SetStatusMessage("Step 3"); 
    await DoStep3(); 
    SetStatusMessage("Completed"); 
} 

ようにそれを作ってみます。しかし、私の推奨は"DoSteps"のコードをviewmodelレベルに置き、ラベルの内容をviewmodelのプロパティにバインドすることです。このようにしてコードビハインドがはるかにクリーンになり、心配する必要はありませんスレッドについては、と思う。

私が注目してきた別のポイントは、命名規則です。要するに、awaitalbleの名前は、後置として名前+ "非同期"を得なければならないので、

+0

あなたの考えに感謝します。上記の私のコードサンプルは単純化されましたが、私の実際のコードでは、あなたが記述する方法でビューモデルと非同期命名規則を正しく使用しています。しかし、私の非同期メソッドは非同期に実行することが不可欠です。あなたが示した方法でそれらを呼び出すと、明示的に非同期的なビット(たとえば、HTTP API呼び出し)が実行されません。 –

+0

githubで問題を生成しているサンプルを作成して、見てみることができますか? 注意問題がある場合は個人的にしか使用できません。私はあなたを助けることができます – BraveHeart

+0

問題を実証できる最も簡単なケースを表示するために質問を更新しました。このサンプルでは、​​非同期メソッドの呼び出しの問題に対処することさえできません。すべてが同期的ですが、それでも期待どおりに動作しません。 –

関連する問題