tags:

views:

67

answers:

3

Hey-

I'm using a MySQL connector in VB .Net to execute a batch of SQL inserts. This is typically on the order of 5k statements and takes around 30 minutes to process. Unfortunately, when this process is running and I use a different application on the system, upon returning to the .net app it hangs and shows "not responding". In fact, as soon as I click anywhere else in the application (move to a different tab, for example) everything locks up.

Dim transaction As MySqlTransaction = sqlConnection.BeginTransaction()
For Each sqlCmd In (sqlCmdsCollection)
    sqlCommand = New MySqlCommand(sqlCmd, sqlConnection)
    Try
        sqlCommand.ExecuteNonQuery()
        logTxtBox.AppendText(". ")
    Catch ex As Exception
        transaction.Rollback()
        logTxtBox.AppendText(vbNewLine & "EXCEPTION: " & ex.Message & vbNewLine)
        logTxtBox.AppendText(sqlCmd & vbNewLine)
        logTxtBox.AppendText("INFO: No changes were made to the database!"& vbNewLine)
    End Try
Next
transaction.Commit()

Why is this happening?

Is there a more efficient way to execute these inserts?

Thanks-

Jonathan

A: 

Sounds like maybe by using another application your system is stealing processing time from a local mysql instance and your app which is ultimately causing mysql to timeout.

There are a couple of ways to "fix" this:

  1. upgrade your local machine, maybe a dual or quad core with sufficient ram.
  2. move the processing to a different machine for execution.
  3. Evaluate your queries to determine why 5000 of them take 30 minutes, that is a really long time.
Chris Lively
+5  A: 

This is because you are calling this long running operation on the UI thread, which means it's blocking and you cannot use the UI whilst this is running.

For short running operations, you can create a delegate which handles the work and invoke that asynchronously and use Control.BeginInvoke to ensure you update the UI on the UI thread.

Anything longer than a few seconds, and as Adam points out, you're better off creating your own Thread and handling your work there.

Having said that, 5000 inserts should really NOT take 30 minutes to run. But that's another question in its own right.

Wim Hollebrandse
-1. No no no! Do not use asynchronous delegate invocation (using `delegate.BeginInvoke`) or anything else that uses the `ThreadPool` for something that takes 30 minutes to run. The `ThreadPool` is designed to host a limited number of short-lived processes, *not* something with a half-hour lifetime. A new thread should be used for this.
Adam Robinson
BeginInvoke uses the ThreadPool too. For long running tasks, one could argue, fire and forget suffices.
Wim Hollebrandse
No, `Control.BeginInvoke` places the delegate into a queue that gets processed on the application thread; it does not use the `ThreadPool` (as otherwise you'd still be using a thread other than the UI thread). "Fire and forget" is irrelevant; it's the fact that it's using the `ThreadPool` that's an issue.
Adam Robinson
The Control.BeginInvoke refers to the updating of the UI, which should run on the application thread. It does not refer to the asynchronous invocation for the long running operation.
Wim Hollebrandse
@Will: I'm not sure what you're getting at. You said "You will need to create a delegate which handles the work and invoke that asynchronously". This sounds like you're recommending calling `BeginInvoke` on the delegate itself, which will use the `ThreadPool`. The problem is using a `ThreadPool` thread for something that's running for 30 minutes. A dedicated thread should be created for this purpose.
Adam Robinson
Yes, that part of it was. And I take your point - edited post. Name's Wim, btw, not Will. You're not the first one to type that (would like to know why people get it wrong in the same way).
Wim Hollebrandse
@Wim: My fault, I guess it's seeing Wi and a couple of vertical lines next to each other that (at a glance) makes it look like Will. In any case, thanks for the edit. +1!
Adam Robinson
Wouldn't BeginExecuteNonQuery be easier? As in my answer
MarkJ
A: 

Other answers are suggesting manually creating a new thread. I think you could just use SqlCommand.BeginExecuteNonQuery which does it all for you? It seems the MySQL driver supports BeginExecuteNonQuery.

MarkJ
If this were a single long-running query, that would be true. However, this is a sequence of queries that need to be executed. Doing this would rapidly fill up the thread pool. A single dedicated thread running the commands in sequence is a much better solution.
Adam Robinson
@Adam, good point. You have contributed a lot to this question.
MarkJ