cancel System.Threading.Tasks.Task on Form_closing
Hi,
I run a new thread on Form1_Load, like this:
Code:
Private cancel_task As New CancellationTokenSource
Private new_task As Task
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'....some code before calling new thread - not relevant IMHO
cancel_task = New CancellationTokenSource
new_task = Task.Factory.StartNew(Sub() Get_Data(SQL), cancel_task.Token)
End Sub
Task in another thread fills Datatable, and I need to cancel that if user closes Form1. I tried this but It doesn't work, I receive error "Invoke or BeginInvoke cannot be called on a control until the window handle has been created.in at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.BeginInvoke(Delegate method, Object[] args)" :
Code:
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
cancel_task.Cancel()
End Sub
I'm not sure If I correctly assigned CancellationToken to Task, or If problem is that inside called Sub() I invoke back to UI thread (in order to bind filled datatable to Datagridview). Or If I'm missing
something in that Sub() which is called from new thread. Here is my Get_Data Sub():
Code:
Sub Get_Data(ByVal Sql As String)
'Fill dataTable
Try
Using conn = New OracleConnection(conn_string)
Using cmd As OracleCommand = New OracleCommand("my_stored_procedure")
cmd.Connection = conn
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(New OracleParameter("SqL_query", OracleDbType.NVarchar2) With {
.Direction = ParameterDirection.Input,
.Value = Sql})
cmd.Parameters.Add(New OracleParameter("result", OracleDbType.RefCursor)).Direction = ParameterDirection.Output
Using da As New OracleDataAdapter
da.SelectCommand = cmd
da.Fill(dt) '- global datatable
End Using
'back to UI thread and set Datagridview datasource to filled datatable
Me.BeginInvoke(Sub() Bind_Datagrid())
Catch ex As Exception
Console.WriteLine(ex.Message + "in " + ex.StackTrace)
End Try
End Sub
Can somebody tell me how to properly cancel working thread ? Thanks in advance !
Re: cancel System.Threading.Tasks.Task on Form_closing
I think I solved my problem. I was missing a lines in Get_Data:
Code:
Sub Get_Data(ByVal Sql As String)
'Fill dataTable
Try
Using conn = New OracleConnection(conn_string)
Using cmd As OracleCommand = New OracleCommand("my_stored_procedure")
cmd.Connection = conn
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(New OracleParameter("SqL_query", OracleDbType.NVarchar2) With {
.Direction = ParameterDirection.Input,
.Value = Sql})
cmd.Parameters.Add(New OracleParameter("result", OracleDbType.RefCursor)).Direction = ParameterDirection.Output
Using da As New OracleDataAdapter
da.SelectCommand = cmd
da.Fill(dt) '- global datatable
End Using
If cancel_task.IsCancellationRequested Then 'This lines are added
Console.WriteLine("thread ended...")
cmd.Cancel()
dt.Rows.Clear()
Exit Sub
End If
'back to UI thread and set Datagridview datasource to filled datatable
Me.BeginInvoke(Sub() Bind_Datagrid())
End using
Catch ex As Exception
Console.WriteLine(ex.Message + "in " + ex.StackTrace)
End Try
End Sub
Please correct me If I'm wrong, but this ends async thread If close Form before Datagridview is bounded with Datatable, which is exactly what I want.