1

ファイル名のリストボックスがあります。選択したインデックスが変更されると、ファイルをロードします。

jQuery の HoverIntent のように、ファイルのロード アクションを短時間遅らせて、ユーザーが下向き矢印を使用して、アプリケーションが各アイテムをロードしようとすることなく、リスト内のアイテムをすばやく循環できるようにする必要があります。Thread.Sleep はアプリ全体を一時停止するため、ユーザーはスリープが完了するまで別のリスト項目を選択できません。これは明らかに私が望んでいるものではありません。

4

3 に答える 3

0

Winフォーム:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private CancellationTokenSource _cancel;
    private object _loadLock = new object();

    private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        lock (_loadLock)
        {

            handleCancellation();

            var loader = new Task((chosenFileItemInListbox) =>
                {
                    Thread.Sleep(1000);
                    LoadFile(chosenFileItemInListbox);
                }, listBox1.SelectedItem, _cancel.Token);
        }
    }

    private bool handleCancellation()
    {
        bool cancelled = false;

        lock (_loadLock)
        {
            if (_cancel != null)
            {
                if (!_cancel.IsCancellationRequested)
                {
                    _cancel.Cancel();
                    cancelled = true;
                }
                _cancel = null;
            } 
        }

        return cancelled;
    }

    private void LoadFile(object chosenFileItemInListbox)
    {
        if (handleCancellation())
        {
            return;
        }
    }
}

上記のコードは WPF にも適用できますが、WPF には、遅延を処理したり以前の更新を取り消したりするためのマジックが組み込まれています。

<ListBox SelectedItem="{Binding Path=SelectedFile, Delay=1000}" />
于 2013-04-02T22:21:04.590 に答える
0

Use Threading to separate the loading from your GUI.

This should get you started:

public partial class MainWindow : Window {

CancellationTokenSource cts;
bool loading;

private void SelectedIndexChanged(int index)
{
    if (loading)
        cts.Cancel();

    cts = new CancellationTokenSource();

    var loader = new Task.Delay(1000);
    loader.ContinueWith(() => LoadFile(index))
          .ContinueWith((x) => DisplayResult(x));

    loader.Start();
}

private void DisplayResult(Task t)
{
    // TODO: Invoke this Method to MainThread
    if (!cts.IsCancellationRequested)
    {
        // Actually display this file
    }
}

Could not test, as I'm still on .net 4 whereas Task.Delay() is .net 4.5 You may need to add another field in the form for the file content transfer from the tasks to the GUI.

于 2013-04-02T22:25:22.720 に答える