在等待Parallel.ForEach的同时实时更新Winforms UI

时间:2012-05-10 14:35:52

标签: c# c#-4.0 asynchronous system.reactive

以下代码无法“实时”运行。目的是,当单击按钮时,验证后台线程上的一组数据。在验证所有数据之前,我不能允许真正的“提交”,但我确实希望文本框能够实时更新。

相反,文本框会立即使用奇数进行更新。

我想现在发生的事情就是task.Wait阻塞了observable,因为我在主线程上观察,但是由于我需要在主线程上进行更新,我无法看到这种方法。

(显然这只是概念证明)

有些相关注意事项 - 此代码是否保证为线程安全?感谢。

private Subject<int> _subject; 
    public Form1()
    {
        InitializeComponent();
    }

    private int sleep = 2000;
    private int i = 0;
    private void LongRunningValidation(int num)
    {
        if (num % 2 == 0) return;

        Thread.Sleep(sleep * (i++));

        _subject.OnNext(num);
    }


    private ConcurrentBag<int> _bag;
    private void simpleButton1_Click(object sender, EventArgs e)
    {
        _subject = new Subject<int>();
        _subject.SubscribeOn(Scheduler.TaskPool).ObserveOn(SynchronizationContext.Current).Synchronize().Subscribe(UpdateTextBox);

        _bag = new ConcurrentBag<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        if(Validate())
        {
            //submit
        }
    }

    private bool Validate()
    {
        var task = Task.Factory.StartNew(StartValidationAsync);

        task.Wait();

        return true;
    }

    private void StartValidationAsync()
    {
        Parallel.ForEach(_bag, LongRunningValidation);
    }

    private void UpdateTextBox(int i)
    {
        textEdit1.Text = textEdit1.Text + "," + i;

    }
}

2 个答案:

答案 0 :(得分:1)

你的Validate方法不是异步的,就像你说阻塞主线程一样。尝试使用事件:

public delegate void ValidatedHandler(bool validate);
public event ValidatedHandler Validated;

private void Validate()
    {
        var task = Task.Factory.StartNew(StartValidationAsync);

        if (Validated != null)
           Validated(true);
    }

订阅活动:

private void simpleButton1_Click(object sender, EventArgs e)
{
    _subject = new Subject<int>();
     _subject.SubscribeOn(Scheduler.TaskPool).ObserveOn(SynchronizationContext.Current).Synchronize().Subscribe(UpdateTextBox);

_bag = new ConcurrentBag<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

this.Validated += OnValidated;
}


public void OnValidated(bool validate)
{
        if(validate)
        {
            //submit
        }
}

答案 1 :(得分:0)

即使您正在运行后台线程,Windows窗体也不会自动更新UI。尝试在要更新的任何内容上调用Update()。