0

Recently, I am using tasks on datagrid controls and in my application there are almost 20 datagrids in different forms.

I do this because sometimes data retrieving takes a long time over database and that freezes the application screen.

Here is my example binding:

string getAlert = "select * from testtable";

DataTable dtAlert = new DataTable();
OracleDataAdapter odaAlert = new OracleDataAdapter();

public void getAlertGrid()
{
    dtAlert.Clear();
    odaAlert = new OracleDataAdapter(getAlert, oradb);
    odaAlert.Fill(dtAlert);
    ugAlert.DataSource = dtAlert;
    ugAlert.DataBind();
}

Task.Factory.StartNew(() => GetAlertGrid());

I would like to know what's your thoughts on it? Is it safe or not?

  • You're going to need to show some code to give us a better idea of what you're talking about. Currently, your question is too open ended. – The Muffin Man Jan 27 '17 at 17:47
  • @TheMuffinMan edited. – S. Zunbag Jan 27 '17 at 17:55
  • WPF of WinForms and show at least one of Task statements – paparazzo Jan 28 '17 at 15:16
  • @Paparazzi added. – S. Zunbag Jan 28 '17 at 15:33
  • Not added. You still do not indicate WPF or WinForms. – paparazzo Jan 28 '17 at 15:39
1

No, this is not safe. There are two issues that immediate come to mind.

Variable access not synchronized

dtAlert and odaAlert are scoped such that they can be accessed by both your main thread and your worker thread. This sort of data access must be synchronized.

Calling UI controls from non-UI thread

Any controls that are created on the UI thread must only be called from the UI thread. That includes your DataTable.

To call a UI control from a worker thread, you must use Invoke. For example, to call DataBind it would look like this:

dtaAlert.Invoke((MethodInvoker)delegate { dtaAlert.DataBind(); });
  • Thanks for the explanation. I tried to convert to 'Invoke, Delegate' method as you said. However I failed. Is that possible to convert above code to that you said Invoke,Delegate way ? I want it, because all of my projects almost building on these datagrids. If it is possible, that i would be grateful. – S. Zunbag Feb 1 '17 at 8:28
0

I do this because sometimes data retrieving takes a long time over database and that freezes the application screen.

You can separate loading data and using it in the UI to different methods, which makes functions responsibilities more clear and no needs for invoking UI controls from another threads.
Then you don't need to re-use same instances of DataTable and DataAdapter.

public DataTable GetAlertData()
{
    var datatable = new DataTable();
    var query = "SELECT * FROM testtable";

    using (var connection = new OracleConnection(connectionString))
    using (var adapter = new OracleDataAdapter(query, connection))
    {
        var datatable = new DataTable();
        adapter.Fill(datatable);
    }

     return datatable;
}

Then wrap this method with task and "await" on it.

var data = await Task.Run(() => GetAlertData());
ugAlert.DataSource = data;

// ugAlert.DataBind();
// In Winforms you don't need to call DataBind - DataGridView does not have such a method.

Much better will be load data "fully" asynchronously by using asynchronous methods of connection, command and data reader. But DataAdapter does not support asynchronous for Fill method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.