取消多线程任务,包括 运行 .dll
Cancel multi-threading Tasks including running .dll
我有 2 个同步启动的不同任务。其中之一是我调用 .dll 来创建 COM 对象(写入 Excel 文件)的方法。当我终止这两个任务时,Excel 文件仍在使用中,所以我无法删除它。这就是我调用这两个任务的方式:
private CancellationTokenSource cancel_1 = new CancellationTokenSource();
private CancellationTokenSource cancel_2 = new CancellationTokenSource();
private void Form1_Load(object sender, System.EventArgs e)
{
cancel_1 = new CancellationTokenSource();
var task_1 = Task.Factory.StartNew(() => DoWork1(), cancel_1.Token);
//2nd task
cancel_2 = new CancellationTokenSource();
var task_2 = Task.Factory.StartNew(() => DoExcelWork(), cancel_2.Token);
}
然后我尝试取消 form_closing 中的两个任务:
private void Form1_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
{
//Cancel all running processes
cancel_1.Cancel();
cancel_2.Cancel();
// I've also set a variable for check if Task_2 is running and try to clear COM
// object with clearing GC(), but It's not working
if (excel_running)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
string filename = Environment.GetFolderPath(Environment.SpecialFolder.Desktop).ToString() + @"\" + "sample.xlsx";
File.Delete(filename)
}
}
但是,这并不是终止由 .dll 启动的写入 Excel 文件的进程。我注意到后台的 运行 进程是 "COM surrogate",所以如您所见,我尝试在 2 个周期内清理 GC(),但文件仍在使用中。
我的线程方法代码是这样的:
public void DoExcelWork()
{
try
{
using (var con = new OracleConnection(conn_string))
{
con.Open();
using (OracleCommand cmd = new OracleCommand("myprocedure"))
{
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("par1", OracleDbType.NVarchar2) { Direction = ParameterDirection.Input, Value = SQL_string });
cmd.Parameters.Add(new OracleParameter("result", OracleDbType.RefCursor)).Direction = ParameterDirection.Output;
//Here is the call of .dll
Export export_xml = new Export();
export_xml.Save_to_Excel(cmd);
excel_running = false;
if (cancel_2.IsCancellationRequested)
{
cmd.Cancel();
return;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + "in " + ex.StackTrace);
}
}
我的问题是 - 如何正确取消后台进程,这样它甚至会关闭 运行 .dll?
已解决。我不得不 re-organize DoExcelWork() 方法来接受 CancellationToken 的附加参数,然后在方法中调用 "token.IsCancellationRequested" 关闭所有正在创建 Excel 文件的对象.
我有 2 个同步启动的不同任务。其中之一是我调用 .dll 来创建 COM 对象(写入 Excel 文件)的方法。当我终止这两个任务时,Excel 文件仍在使用中,所以我无法删除它。这就是我调用这两个任务的方式:
private CancellationTokenSource cancel_1 = new CancellationTokenSource();
private CancellationTokenSource cancel_2 = new CancellationTokenSource();
private void Form1_Load(object sender, System.EventArgs e)
{
cancel_1 = new CancellationTokenSource();
var task_1 = Task.Factory.StartNew(() => DoWork1(), cancel_1.Token);
//2nd task
cancel_2 = new CancellationTokenSource();
var task_2 = Task.Factory.StartNew(() => DoExcelWork(), cancel_2.Token);
}
然后我尝试取消 form_closing 中的两个任务:
private void Form1_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
{
//Cancel all running processes
cancel_1.Cancel();
cancel_2.Cancel();
// I've also set a variable for check if Task_2 is running and try to clear COM
// object with clearing GC(), but It's not working
if (excel_running)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
string filename = Environment.GetFolderPath(Environment.SpecialFolder.Desktop).ToString() + @"\" + "sample.xlsx";
File.Delete(filename)
}
}
但是,这并不是终止由 .dll 启动的写入 Excel 文件的进程。我注意到后台的 运行 进程是 "COM surrogate",所以如您所见,我尝试在 2 个周期内清理 GC(),但文件仍在使用中。
我的线程方法代码是这样的:
public void DoExcelWork()
{
try
{
using (var con = new OracleConnection(conn_string))
{
con.Open();
using (OracleCommand cmd = new OracleCommand("myprocedure"))
{
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("par1", OracleDbType.NVarchar2) { Direction = ParameterDirection.Input, Value = SQL_string });
cmd.Parameters.Add(new OracleParameter("result", OracleDbType.RefCursor)).Direction = ParameterDirection.Output;
//Here is the call of .dll
Export export_xml = new Export();
export_xml.Save_to_Excel(cmd);
excel_running = false;
if (cancel_2.IsCancellationRequested)
{
cmd.Cancel();
return;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + "in " + ex.StackTrace);
}
}
我的问题是 - 如何正确取消后台进程,这样它甚至会关闭 运行 .dll?
已解决。我不得不 re-organize DoExcelWork() 方法来接受 CancellationToken 的附加参数,然后在方法中调用 "token.IsCancellationRequested" 关闭所有正在创建 Excel 文件的对象.