如何在后台线程中连接到远程服务器上的数据库?

时间:2009-04-03 00:47:02

标签: c# multithreading linq-to-sql

我有一个Windows窗体,我在其上显示本地数据库中的数据。

我还要连接到远程数据库,并从那里显示一些其他数据..但是,这个远程数据库可能已关闭或缓慢。

当我尝试连接到此远程数据库时,我不希望UI冻结。

所以对线程或线程安全一无所知,这是我的一个例子:

RemoteDataContext rdt;

private void GetRemoteDataContext() {
    rdt = new RemoteDataContext(RemoteServerConnectionString);
}

private void FillFromRemoteDataContext() {
   lblTest.text = rdt.TestTable.First().TestField;
}

private void Form1_Shown(object sender, EventArgs e) {
    Thread t = new Thread(new ThreadStart(new delegate {
        try {
            GetRemoteDataContext();
            FillFromRemoteDataContext();
        } catch { }  // ignore connection errors, just don't display data
    );
    t.Start;
}

所以你应该能够从中得知我想要实现的目标。

我的问题是,正确的方法是什么?


更新:谢谢大家,我现在(Form1Shown):

BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler((sender, e) => {
    e.Result = null;
    try {
        e.Result = new RemoteDataContext(RemoteServerConnectionString);
    } catch { } // ignore connection errors, just don't display data
});
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler((sender, e) => {
    if (e.Result != null) {
        rdt = (RemoteDataContext)e.Result;
        FillFromRemoteDataContext();            
    }
});
bw.RunWorkerAsync();

它有效,据我所知,应该没有与线程相关的错误。

2 个答案:

答案 0 :(得分:2)

您可能想要查看BackgroundWorker课程,这会让事情变得更容易。

您只需为实际工作,进度报告和线程完成指定委托。

答案 1 :(得分:1)

这就是我如何做到这一点,但是当数据库连接成功并且您需要更新UI时,您将遇到的问题是跨线程访问。正如CMS建议您可以使用BackgroundWorker类并让它为您处理跨线程编组。我倾向于采用更细粒度的控制,我会将你的例子实现为:

RemoteDataContext rdt;
private void GetRemoteDataContext() {    
   rdt = new RemoteDataContext(RemoteServerConnectionString);
}
private void FillFromRemoteDataContext() { 
    if (lblTest.Dispatcher.Thread != Thread.CurrentThread) {
        lblTest.Dispatcher.Invoke(delegate { lblTest.text = rdt.TestTable.First().TestField}); 
    } 
    else {
        lblTest.text = rdt.TestTable.First().TestField;
    }
}
private void Form1_Shown(object sender, EventArgs e) {    
    ThreadPool.QueueUserWorkItem(delegate {        
        try {            
            GetRemoteDataContext();            
            FillFromRemoteDataContext();        
        } catch { }  // ignore connection errors, just don't display data   
    });    
}