0

余分なスレッドを使用せずに、大量のデータの読み取りまたは書き込みが行われているときに、「読み込み中」のラベルなどをユーザーに表示したいと思います。ただし、IOメソッドを呼び出す前にUI要素を変更しようとすると、アプリケーションがしばらくフリーズし、すべての作業が完了したに「読み込み中」メッセージが表示されます。これは明らかに役に立ちません。IOメソッドを呼び出す前に、UIの変更が適用されて表示されていることを確認するにはどうすればよいですか?

        DataSet ds = STT_Import.ImportExcelToDataSet(filePath);

        bool result = false;

        if (ds != null)
        {
            int cellCount = ds.GetTotalCellCount();

            if (Popup.ShowMessage(string.Format("Your file contains {0} cells. Inserting data will take approximately {1} seconds. Do you want to continue?",
                cellCount, CalculateTime(cellCount)), "Confirm", MessageType.Confirm) == MessageBoxResult.Yes)
            {
                // Tell user the application is working:
                StatusLabel.Content = "Writing to database...";

                // Do actual work after user has been notified:
                result = DB.StoreItems(_currentType, ds);
            }
        }

答えを探してみましたが、具体的な質問に答えるものが見つからなかったので、以前に質問されたことがある場合は申し訳ありません。

4

5 に答える 5

1

WPFを使用する場合、Dispatcherを使用して、さまざまなDispatcherPrioritiesのUIスレッドでコマンドをキューに入れることができます。

これにより、またはキュー内のすべてが発生した、UIスレッドで実行時間の長いプロセスをキューに入れることができます。DispatcherPriority.RenderDispatcherPriority.Loaded

たとえば、コードは次のようになります。

// Tell user the application is working:
StatusLabel.Content = "Writing to database...";

// Do actual work after user has been notified:
Dispatcher.BeginInvoke(DispatcherPriority.Input,
    new Action(delegate() { 
        var result = DB.StoreItems(_currentType, ds);     // Do Work
        if (result)
            StatusLabel.Content = "Finished";
        else
            StatusLabel.Content = "An error has occured";
     }));

ただし、通常、何かの実行中にアプリケーションをロックするのは悪い設計と見なされていることに注意してください。

より良い解決策は、バックグラウンドスレッドで長時間実行プロセスを実行し、実行中はアプリケーションフォームを無効にすることです。これを行うには多くの方法がありますが、私の個人的な好みは、その単純さのためにタスク並列ライブラリを使用することです。

例として、バックグラウンドスレッドを使用するコードは次のようになります。

using System.Threading.Tasks;

...

// Tell user the application is working:
StatusLabel.Content = "Writing to database...";
MyWindow.IsEnabled = False;

// Do actual work after user has been notified:
Task.Factory.StartNew(() => DB.StoreItems(_currentType, ds))
    // This runs after background thread is finished executing
    .ContinueWith((e) =>
    {
        var isSuccessful = e.Result;

        if (isSuccessful)
            StatusLabel.Content = "Finished";
        else
            StatusLabel.Content = "An error has occured";

        MyWindow.Enabled = true;
    });
于 2013-02-11T17:51:29.263 に答える
0

あなたが使用しているアプローチは効率的な方法ではないので、非同期プログラミングまたはスレッド化を使用することをお勧めします

非同期プログラミング:

Visual Studio 2012では、.NETFramework4.5およびWindowsランタイムでの非同期サポートを活用する単純化されたアプローチである非同期プログラミングが導入されています。コンパイラーは、開発者が行っていた困難な作業を実行し、アプリケーションは同期コードに似た論理構造を保持します。その結果、わずかな労力で非同期プログラミングのすべての利点を得ることができます。.Net Framework 4.5をサポート
します。これにより、System .Threadingの実装にかかる時間を節約でき、操作を待機する必要がある場合と同じタスクを非常に効率的に実行できます。

http://msdn.microsoft.com/en-ca/library/vstudio/hh191443.aspx
http://go.microsoft.com/fwlink/?LinkID=261549

また

糸脱毛:

スレッド化の利点は、複数の実行スレッドを使用するアプリケーションを作成できることです。たとえば、プロセスには、ユーザーとの対話を管理するユーザーインターフェイススレッドと、ユーザーインターフェイススレッドがユーザー入力を待機している間に他のタスクを実行するワーカースレッドを含めることができます。.Netfremework4.0以前をサポート

http://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx

于 2013-02-11T15:46:16.887 に答える
0

あなたは間違った方法で問題を解決しようとしています。ここで行うべきことは、ワーカースレッドで時間のかかるタスクを実行することです。このようにすると、UIの応答性が維持さ、現在の質問は無意味になります。

タスクをワーカースレッドにオフロードする方法はいくつかあります。最も便利なのは、スレッドプール非同期プログラミングの使用です。

于 2013-02-11T15:46:16.970 に答える
0

データベースが使用しているメソッドの非同期バージョンを提供しない限り、追加のスレッドを利用せずにUIの応答性を維持することはおそらく不可能です。メソッドの非同期バージョンを提供する場合、それを使用する必要があります。(非同期は、他のスレッドを使用していることを意味するものではないことに注意してください追加のスレッドを使用しない非同期メソッドを作成することは完全に可能であり、それはほとんどのネットワークIOメソッドで行われていることです。)実行方法の詳細これは、使用しているDBフレームワークのタイプとその使用方法によって異なります。

DBフレームワークが非同期メソッドを提供していない場合、UIの応答性を維持する唯一の方法は、UI以外のスレッドで長時間実行される操作を実行することです。

于 2013-02-11T15:56:50.087 に答える
0

UIの応答性を望まない場合は、ビジーインジケーターを使用します。
よりきれいなカーソルがあります-これは社内アプリケーションです。

using (new WaitCursor())
{
    // very long task
    Search.ExecuteSearch(enumSrchType.NextPage);
}

public class WaitCursor : IDisposable
{
    private Cursor _previousCursor;

    public WaitCursor()
    {
        _previousCursor = Mouse.OverrideCursor;

        Mouse.OverrideCursor = Cursors.Wait;
    }

    #region IDisposable Members

    public void Dispose()
    {
        Mouse.OverrideCursor = _previousCursor;
    }

    #endregion
}
于 2013-02-11T17:25:51.403 に答える