0

Web から 2 つの JSON ファイルをダウンロードしています。その後、2 つのページの読み込みを許可したいのですが、その前には許可したくありません。ただし、ManualResetEventページをロードするために設定する必要がある は「起動」しません。セットされることはわかっていますが、WaitOne決して戻りません。

ダウンロードを開始する方法:

private void Application_Launching(object sender, LaunchingEventArgs e)
{
    PhoneApplicationService.Current.State["doneList"] = new List<int>();
    PhoneApplicationService.Current.State["manualResetEvent"] = new ManualResetEvent(false);

    Helpers.DownloadAndStoreJsonObject<ArticleList>("http://arkad.tlth.se/api/get_posts/", "articleList");
    Helpers.DownloadAndStoreJsonObject<CompanyList>("http://arkad.tlth.se/api/get_posts/?postType=webbkatalog", "catalog");
}

を設定するダウンロード方法ManualResetEvent

public static void DownloadAndStoreJsonObject<T>(string url, string objName)
{
    var webClient = new WebClient();
    webClient.DownloadStringCompleted += (sender, e) => 
    {
        if (!string.IsNullOrEmpty(e.Result))
        {
            var obj = ProcessJson<T>(e.Result);
            PhoneApplicationService.Current.State[objName] = obj;


            var doneList = PhoneApplicationService.Current.State["doneList"] as List<int>;
            doneList.Add(0);

            if (doneList.Count == 2)    // Two items loaded
            {
                (PhoneApplicationService.Current.State["manualResetEvent"] as ManualResetEvent).Set();  // Signal that it's done
            }
        }
    };

    webClient.DownloadStringAsync(new Uri(url));
}

待機メソッド (この場合はコンストラクター)

public SenastePage()
{
    InitializeComponent();

    if ((PhoneApplicationService.Current.State["doneList"] as List<int>).Count < 2)
    {
        (PhoneApplicationService.Current.State["manualResetEvent"] as ManualResetEvent).WaitOne();
    }
    SenasteArticleList.ItemsSource =  (PhoneApplicationService.Current.State["articleList"] as ArticleList).posts;
}

そのコンストラクターにアクセスしようとする前に待機すると、if ステートメントを簡単に通過し、WaitOne.

何か案は?

4

2 に答える 2

1

UI スレッドのブロックは、何としてでも防止する必要があります。特にデータをダウンロードするときは、ネットワークが非常に不安定な電話でアプリケーションを実行していることを忘れないでください。データの読み込みに 2 分かかる場合、UI は 2 分間フリーズします。それはひどいユーザーエクスペリエンスになります。

それを防ぐ方法はたくさんあります。たとえば、UI スレッドではなくバックグラウンド スレッドで待機しながら、同じロジックを維持できます。

public SenastePage()
{
    // Write the XAML of your page to display the loading animation per default
    InitializeComponent();

    Task.Factory.StartNew(LoadData);
}

private void LoadData()
{
    ((ManualResetEvent)PhoneApplicationService.Current.State["manualResetEvent"]).WaitOne();

    Dispatcher.BeginInvoke(() =>
    {
        SenasteArticleList.ItemsSource = ((ArticleList)PhoneApplicationService.Current.State["articleList"]).posts;

        // Hide the loading animation
    }
}

それはあなたが望む結果に到達するための簡単で汚い方法です。タスクを使用してコードを書き直し、タスクTask.WhenAllがすべて終了したときにアクションをトリガーするために使用することもできます。

于 2013-10-20T19:07:46.993 に答える
0

ロジックに問題があるのか​​もしれません。SenastePage() コンストラクターでは、doneListカウントが 2 未満の場合にのみ set イベントを待機しています。doneListただし、カウントが 2 になるまで set イベントは発生しません。set イベントが発生する前にリッスンしています。

于 2013-10-20T18:51:16.720 に答える