1

[Windows 窗体应用程序和 .NET 4.0]

我需要执行返回对象(类列表或简单类)的数据库访问方法。

我还需要在主线程进行初始化时打开响应式表单。

我需要在单独的线程上运行这些,以保持用户界面的响应,当然还需要能够将结果传递回主线程以进行 UI 更新。

我一直在阅读有关各种方法的书籍。

我了解我的工作可以通过以下方式完成:

  • 背景地勤工作者
  • 线程类
  • 任务类

我应该潜入哪一个?

更新:使用建议的任务类,我使用以下方法获取跨线程安全错误:

private void BtnCheckClick(object sender, EventArgs e)
{
    var itm =   Task<JDEItemLotAvailability>.Factory.StartNew(() =>
                             Dal.GetLotAvailabilityF41021(
                                                         txtLot.Text,
                                                         cmbMcu.SelectedItem.ToString(),
                                                         cmbLocn.SelectedItem.ToString())
                            );
       lblDescriptionValue.Text = itm.Result.Description;
       lblItemCodeValue.Text = itm.Result.Code;
       lblQuantityValue.Text = itm.Result.AvailableQuantity.ToString();
       LotFocus(true);
}

在上面的例子中,我在 cmbMcu 控件而不是 txtLot 中得到了异常。

4

2 回答 2

1

我已经使用 Thread 完成了很多项目,但是 Task 应该更易于使用。

这是演示如何使用线程进行异步操作。

这是将数据返回到 ui 的类:

public class MyAsyncClass
{

    public delegate void NotifyComplete(DataSet data);
    public event NotifyComplete NotifyCompleteEvent;

    //Starts async thread...
    public void Start()
    {
        System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(DoSomeJob));
        t.Start();
    }

    void DoSomeJob()
    {
        //just wait 5 sec for nothing special...
        System.Threading.Thread.Sleep(5000);
        if (NotifyCompleteEvent != null)
        {
            //TODO: fill your data...
            DataSet ds = new System.Data.DataSet();

            NotifyCompleteEvent(ds);
        }
    }
}

这是ui实现:

    MyAsyncClass myClass = null;


    private void button2_Click(object sender, EventArgs e)
    {
        myClass = new MyAsyncClass();
        myClass.NotifyCompleteEvent += new MyAsyncClass.NotifyComplete(myClass_NotifyCompleteEvent);
        //here I start the job inside working class...
        myClass.Start();
    }

    //here my class is notified from working class when job is completed...
    delegate void myClassDelegate(DataSet data);
    void myClass_NotifyCompleteEvent(DataSet data)
    {
        if (this.InvokeRequired)
        {
            Delegate d = new myClassDelegate(myClass_NotifyCompleteEvent);
            this.Invoke(d, new object[] { data });
        }
        else
        {
            //TODO: show your data
            MessageBox.Show("Data retrieved!");
        }
    }
于 2012-12-01T20:32:15.980 回答
1

我会使用这个Task类,同步它真的很容易,而且它已经为返回对象提供了支持。

var task = Task.Factory.StartNew(
    () => GetDatabaseData(someArguments),
    TaskCreationOptions.LongRunning);

// Example method
public DataSet GetDatabaseData(object args) { ... }

这告诉调度程序创建并开始一个新任务,并暗示如果调度程序使用线程池,不使用线程池线程可能是个好主意。无论如何,您现在可以决定如何同步。

例如,要实现与 Gregor Primar 的答案类似的行为,您可以使用ContinueWith以下方法设置延续,

task.ContinueWith(oldTask => ProcessReturnedData(oldTask.Result));

// Example method
public IEnumerable<SomeEntity> ProcessReturnedData(DataSet data) { ... }

这将安排在对象完成执行ProcessReturnedData后调用该方法。task请注意,即使task由于某种原因失败,它也会被调用,因此它可能并不总是一个好的解决方案 - 或者您必须在提供的委托中进行一些检查。

如果您想在主线程上进行非阻塞等待并在那里使用返回的对象,您可以简单地使用该Wait方法。

task.Wait(); // Makes current thread wait until the task is comnpleted.
DataSet result = task.Result; // Accessing the result object.
于 2012-12-01T22:34:58.897 回答