简体   繁体   中英

How can I connect to a database on a remote server in a background thread?

I have a windows form, on which I display data from a local database.

I'd like to also connect to a remote database, and display some other data from there.. however, this remote database could be down, or slow.

I don't want the UI to freeze while I try to connect to this remote database.

So knowing nothing about threading or thread-safety, here's my hamfisted example:

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;
}

So you should be able to tell from that what it is that I want to acheive.

My question is, what is the correct way to go about it?


Update: Thanks guys, now I have (in 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();

And it works, and as far as I understand it, there should be no threading related errors.

You might want to check the BackgroundWorker class, it will make things a lot easier.

You only have to specify delegates for the actual work, for the progress reporting and the thread completion.

Thats along the lines of how I'd do it but the issue you will have is cross thread access when your database connection does succeed and you need to update your UI. As CMS suggests you could use the BackgroundWorker class and have it take care of the cross-thread marshalling for you. I tend to go for more fine grained control and I would implement you example as:

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   
    });    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM