How can I connect to a database on a remote server

2019-06-13 17:53发布

问题:

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.

回答1:

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.



回答2:

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