Task.StartNew在运行时保存主线程

时间:2012-12-02 20:44:51

标签: c# .net winforms multithreading

在此代码运行时,我无法移动或在我的UI中执行任何操作:

var a = txtLot.Text;
var b = cmbMcu.SelectedItem.ToString();
var c = cmbLocn.SelectedItem.ToString();

var itm = Task<JDEItemLotAvailability>
.Factory.StartNew(() =>
{
        btnCheck.BackColor = Color.Red;
        var ret = Dal.GetLotAvailabilityF41021(a, b, c);
        btnCheck.BackColor = Color.Transparent;
        return ret;
}
    );
lblDescriptionValue.Text = itm.Result.Description;
lblItemCodeValue.Text = itm.Result.Code;
lblQuantityValue.Text = itm.Result.AvailableQuantity.ToString();

我尝试评论对Dal方法的调用并改为使用thread.sleep(5000),但我仍然无法移动表单。

编辑:也许我用错误的方法取回结果?

更新

在第一次回复(John's)之后,我尝试了这个:

var a = txtLot.Text;
var b = cmbMcu.SelectedItem.ToString();
var c = cmbLocn.SelectedItem.ToString();

var itm = Task<JDEItemLotAvailability>
.Factory.StartNew(() =>
{
        btnCheck.BackColor = Color.Red;
        var ret = Dal.GetLotAvailabilityF41021(a, b, c);
        btnCheck.BackColor = Color.Transparent;
        return ret;
}
    ).ContinueWith(itm =>
{
lblDescriptionValue.Text = itm.Result.Description;
lblItemCodeValue.Text = itm.Result.Code;
lblQuantityValue.Text = itm.Result.AvailableQuantity.ToString();
});

但当然我再次弄乱ui ....表格冻结消失了,但是当任务结束时发生了异常

1 个答案:

答案 0 :(得分:4)

这里有两个问题。

首先,您的代码试图从几乎可以肯定是不同的线程(即在任务中,可能在线程池线程中执行)访问UI线程。你不应该这样做。

其次,你在这里阻止了UI线程:

lblDescriptionValue.Text = itm.Result.Description;

访问itm.Result属性将阻止,直到任务完成。您不希望这样做 - 这次 UI线程中 - 因为这会冻结您的UI,正如您所观察到的那样。

如果你正在使用C#5和.NET 4.5,你可以尝试使用新的异步功能 - 这可能会让更多更容易做你想做的事。

如果您不能使用.NET 4.5(或.NET 4的异步定位包),则应使用Task.ContinueWith告诉Task完成后您要执行的操作。

编辑:我怀疑你想要的东西:

var a = txtLot.Text;
var b = cmbMcu.SelectedItem.ToString();
var c = cmbLocn.SelectedItem.ToString();

btnCheck.BackColor = Color.Red;
var task = Task.Factory.StartNew(() => Dal.GetLotAvailabilityF41021(a, b, c));
task.ContinueWith(t =>
{
    btnCheck.BackColor = Color.Transparent;
    lblDescriptionValue.Text = t.Result.Description;
    lblItemCodeValue.Text = t.Result.Code;
    lblQuantityValue.Text = t.Result.AvailableQuantity.ToString();
}, TaskScheduler.FromCurrentSynchronizationContext());