Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在单独的线程中运行返回对象的数据库访问任务并保持UI响应的最佳方法?_C#_.net_Multithreading_Data Access Layer_Splash Screen - Fatal编程技术网

C# 在单独的线程中运行返回对象的数据库访问任务并保持UI响应的最佳方法?

C# 在单独的线程中运行返回对象的数据库访问任务并保持UI响应的最佳方法?,c#,.net,multithreading,data-access-layer,splash-screen,C#,.net,Multithreading,Data Access Layer,Splash Screen,[Windows窗体应用程序和.NET 4.0] 我需要执行返回对象(类列表或简单类)的数据库访问方法 我还需要在主线程进行初始化时打开响应的表单 我需要在不同的线程上运行它们,以保持用户界面的响应性,当然,还需要能够将结果传递回主线程以进行UI更新 我一直在阅读有关这方面各种方法的书籍 我理解我的工作可以通过以下方式完成: 幕后工作者 螺纹类 任务类 我应该跳哪一个 更新:使用建议的任务类,我得到了errot,用于跨线程安全,使用以下命令: private void BtnCheckCli

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

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

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

我需要在不同的线程上运行它们,以保持用户界面的响应性,当然,还需要能够将结果传递回主线程以进行UI更新

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

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

  • 幕后工作者
  • 螺纹类
  • 任务类
我应该跳哪一个

更新:使用建议的任务类,我得到了errot,用于跨线程安全,使用以下命令:

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);
}
private void BtnCheckClick(对象发送方,事件参数e)
{
var itm=Task.Factory.StartNew(()=>
Dal.GetLotAvailabilityF41021(
txtLot.Text,
CMBMU.SelectedItem.ToString(),
cmbLocn.SelectedItem.ToString())
);
lblDescriptionValue.Text=itm.Result.Description;
lblItemCodeValue.Text=itm.Result.Code;
lblQuantityValue.Text=itm.Result.AvailableQuantity.ToString();
LotFocus(真);
}

在上面的exmaple中,我在CMBMUCU控件中遇到异常,而不是txtLot。

我使用线程完成了很多项目,但是任务应该更易于使用

下面是如何使用线程进行异步操作的演示

这是将数据返回到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!");
        }
    }
我会使用类,它非常容易同步,并且已经提供了对返回对象的支持

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

// Example method
public DataSet GetDatabaseData(object args) { ... }
这会告诉创建并开始一个新任务,并提示如果调度程序使用线程池,则最好不要使用线程池线程。无论如何,您现在可以决定如何同步

例如,为了实现与Gregor Primar的答案中类似的行为,您可以使用方法设置一个continuation,如下所示:

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

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

有什么东西阻止你跳到.NET4.5吗?async/await使任务处理更干净。我需要在一些旧的或者XP上运行,这是我唯一的障碍…我被限制在一些Windows XP机器上,所以我不能使用.NET 4.5的新功能,所以我认为我将坚持使用任务类。Backgroundworker往往已经过时了?我认为在Windows窗体应用程序中使用Backgroundworker是完全可以的-它是作为Windows窗体组件设计的。但是我发现任务在处理它们的方式上更高级,它们是旨在简化使用的新概念,所以如果你能使用它们,我推荐它。BackgroundWorker可能也是一个选项,例如它支持报告进度,因此,您可以简单地将其挂接到进度条并进行更新-但您在问题中没有提到这方面的需要,而且我认为对于数据库操作来说,这没有多大意义。谢谢,但如果我只运行类似以下内容,它将不会更简单:
var pi=Task.Factory.StartNew(()=>ComputePi(numDigits))。。。控制台写入线(pi.Result)并直接将结果获取到我的ui?毕竟,我最想做的是运行一个方法并将数据库结果返回到我的主线程。对于许多GUI框架来说,这是一件事——您需要在GUI线程(通常是主线程)上进行UI更改(或更改“表单”类)。您的示例在
numDigits
变量上创建了一个变量,这可能是一个问题。尝试将其作为参数传递给lambda,而不是直接传递给ComputePi方法:
Task.Factory.StartNew(num=>ComputePi(num),numDigits)问题已解决,将其添加到问题中以确保完整性。谢谢
task.Wait(); // Makes current thread wait until the task is comnpleted.
DataSet result = task.Result; // Accessing the result object.