2016-05-10 12 views
0

私のコードはかなり次のようになります。GUIで非同期タスクがAIアニメーションをフリーズするのはなぜですか?

namespace CloudKey 
{ 
/// <summary> 
/// Interaction logic for Page1.xaml 
/// </summary> 
public partial class Page1 : Page 
{ 
    public Page1() 
    { 
     InitializeComponent(); 
    } 

    private async void button_Click(object sender, RoutedEventArgs e) 
    { 
     //Begin Loading animation 
     Loading.Visibility = Visibility.Visible; 

     //Run Task 
     await Task.Run(() => LoginCheck()); 
    } 

    async void LoginCheck() 
    { 
     await Dispatcher.InvokeAsync(
       () => 
       { 
        InitialSessionState iss = InitialSessionState.CreateDefault(); 
        StringBuilder ss = new StringBuilder(); 
        ss.AppendLine("some code here") 
        using (Runspace runspace = RunspaceFactory.CreateRunspace(iss)) 
        { 
         Collection<PSObject> results = null; 
         try 
         { 
          runspace.Open(); 
          Pipeline pipeline = runspace.CreatePipeline(); 
          pipeline.Commands.AddScript(ss.ToString()); 
          results = pipeline.Invoke(); 

         } 
         catch (Exception ex) 
         { 
          results.Add(new PSObject((object)ex.Message)); 
         } 
         finally 
         { 
          runspace.Close(); 
          Loading.Visibility = Visibility.Hidden; 
          if //some stuff 
          { 
           //do some things 
          } 
          else 
          { 
           //do some other things 
          } 
         } 
        } 
       }); 
    } 
    } 
} 

私も同じ結果と

Async void LoginCheck() 
{ 
    await Dispatcher.Invoke (() => {//Stuff}); 
} 

を試してみました。私は実際には2つの違いが何であるか実際にはわかりません...

タスクはどちらかの方法で正しく実行されますが、タスクが開始するとすぐにアニメーションが開始してフリーズします。 :/私はこの作業を、機能を通してアニメーション化されている読み込みアニメーションと同じようにするために何をすべきですか?

編集:私はそうするとき、私は私が

await Dispatcher.InvokeAsync(
      () =>{}); 

を削除し、タクトで関数の残りの部分を残すようにしようとしたことを追加する必要があり

、しかし、私は次のエラーを取得する:

The calling thread cannot access this object because a different thread owns it. 
+2

新しいスレッドプールスレッドに何もせず、UIスレッドに一連のコードを実行させるように指示しています。したがって、すべてのコードがUIスレッドで実行されることが期待されます。 UIスレッドの外部でコードを実行する場合は、実際にUIスレッドの外部でコードを実行する必要があります。 – Servy

+0

私は理解しているか分からない...あなたは例を挙げることができますか? –

+2

*例を挙げました。 UIスレッドですべてのコードを実行しており、すべてのコードがUIスレッドで実行されていると不平を言っています。 – Servy

答えて

1

私は必要だとすべてが

await Dispatcher.InvokeAsync(() => { }; 
を削除することだと思いますコードを囲む

Dispatcher.InvokeAsyncのドキュメントを見ると、「Dispatcherが関連付けられているスレッドで、指定されたデリゲートを非同期に実行します」と表示されます。 (source)ページにリンクされているDispatcherはページのスレッドに関連付けられているため、UIスレッドでコードを実行しています。その周囲の関数呼び出しを削除すると、別のスレッドでコードを実行する必要があります。これは、既にTask.Run()を呼び出して別のスレッドで実行しているためです。

EDIT:UIスレッドが所有しているローディングが変更された部分を紛失しました。ここでは、より良い問題を示し、実際のコードサンプルです:

async void LoginCheck() 
{ 
    InitialSessionState iss = InitialSessionState.CreateDefault(); 
    StringBuilder ss = new StringBuilder(); 
    ss.AppendLine("some code here") 
    using (Runspace runspace = RunspaceFactory.CreateRunspace(iss)) 
    { 
     Collection<PSObject> results = null; 
     try 
     { 
      runspace.Open(); 
      Pipeline pipeline = runspace.CreatePipeline(); 
      pipeline.Commands.AddScript(ss.ToString()); 
      results = pipeline.Invoke(); 

     } 
     catch (Exception ex) 
     { 
      results.Add(new PSObject((object)ex.Message)); 
     } 
     finally 
     { 
      runspace.Close(); 
      Dispatcher.InvokeAsync(() => { 
       Loading.Visibility = Visibility.Hidden; 
      }); 

      if //some stuff 
      { 
       //do some things 
      } 
      else 
      { 
       //do some other things 
      } 
     } 
    } 
} 

Loading.VisibilityがUI要素であるので、それはUIスレッドが所有しています。そのため、Dispatcher.Invoke()を呼び出しただけで、UIスレッドからその値が変更され、上記のように他のスレッドでdbコールが実行されます。

+0

エラーが発生します:呼び出し元のスレッドは、別のスレッドが所有しているため、このオブジェクトにアクセスできません。 –

+1

@NickG問題が見つかりましたので、答えを編集しました。そのLoading.Visibility呼び出しに気付かなかった。 –

+0

デバッグ後、そのスレッドからUI関数を呼び出したためです。あなたの提案はうまくいった! –

関連する問題