如下程序,开两个线程,向同一个worksheet中的不同行写入数据,
在第一遍执行的时候,两个线程中会随机有一个线程报错,再次执行就正常了,求高手指点。
class ExPara
{
private Microsoft.Office.Interop.Excel.Worksheet _WorkSheet;
public Microsoft.Office.Interop.Excel.Worksheet WorkSheet
{
get { return _WorkSheet; }
set { _WorkSheet = value; }
}
private int _StartRow;
public int StartRow
{
get { return _StartRow; }
set { _StartRow = value; }
}
private String _Value;
public String Value
{
get { return _Value; }
set { _Value = value; }
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private int x = 2;//线程计数,完成一个减一
Microsoft.Office.Interop.Excel.Application ex;
Microsoft.Office.Interop.Excel.Workbook wb;
Microsoft.Office.Interop.Excel.Worksheet ws;
/// <summary>
/// 开始程序
/// </summary>
private void ThreadExcel()
{
try
{
ex = new Microsoft.Office.Interop.Excel.Application();
wb = ex.Workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets[1];
x = 2;
Thread t1 = new Thread(new ParameterizedThreadStart(T));
ExPara e1 = new ExPara();
e1.WorkSheet = ws;
e1.StartRow = 1;
e1.Value = “测试线程1”;
t1.Start(e1);
Thread t2 = new Thread(new ParameterizedThreadStart(T));
ExPara e2 = new ExPara();
e2.WorkSheet = ws;
e2.StartRow = 5;
e2.Value = “测试线程2″;
t2.Start(e2);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
/// <summary>
/// 执行
/// </summary>
/// <param name=”ex”></param>
private void T(object ex)
{
try
{
ExPara e = ex as ExPara;
(ws.Cells[e.StartRow, 1] as Microsoft.Office.Interop.Excel.Range).Value2 = e.Value;
}
catch (Exception e1)
{
MessageBox.Show((ex as ExPara).Value);
MessageBox.Show(e1.Message);
}
finally
{
x–;
ShowExcel();
}
}
/// <summary>
/// 显示表格
/// </summary>
private void ShowExcel()
{
try
{
if (x == 0)
{
ex.Visible = true;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
finally
{
if (x == 0)
{
if (ws != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
if (wb != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
if (ex != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(ex);
GC.Collect();
}
}
}
}
在第一遍执行的时候,两个线程中会随机有一个线程报错,再次执行就正常了,求高手指点。
class ExPara
{
private Microsoft.Office.Interop.Excel.Worksheet _WorkSheet;
public Microsoft.Office.Interop.Excel.Worksheet WorkSheet
{
get { return _WorkSheet; }
set { _WorkSheet = value; }
}
private int _StartRow;
public int StartRow
{
get { return _StartRow; }
set { _StartRow = value; }
}
private String _Value;
public String Value
{
get { return _Value; }
set { _Value = value; }
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private int x = 2;//线程计数,完成一个减一
Microsoft.Office.Interop.Excel.Application ex;
Microsoft.Office.Interop.Excel.Workbook wb;
Microsoft.Office.Interop.Excel.Worksheet ws;
/// <summary>
/// 开始程序
/// </summary>
private void ThreadExcel()
{
try
{
ex = new Microsoft.Office.Interop.Excel.Application();
wb = ex.Workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets[1];
x = 2;
Thread t1 = new Thread(new ParameterizedThreadStart(T));
ExPara e1 = new ExPara();
e1.WorkSheet = ws;
e1.StartRow = 1;
e1.Value = “测试线程1”;
t1.Start(e1);
Thread t2 = new Thread(new ParameterizedThreadStart(T));
ExPara e2 = new ExPara();
e2.WorkSheet = ws;
e2.StartRow = 5;
e2.Value = “测试线程2″;
t2.Start(e2);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
/// <summary>
/// 执行
/// </summary>
/// <param name=”ex”></param>
private void T(object ex)
{
try
{
ExPara e = ex as ExPara;
(ws.Cells[e.StartRow, 1] as Microsoft.Office.Interop.Excel.Range).Value2 = e.Value;
}
catch (Exception e1)
{
MessageBox.Show((ex as ExPara).Value);
MessageBox.Show(e1.Message);
}
finally
{
x–;
ShowExcel();
}
}
/// <summary>
/// 显示表格
/// </summary>
private void ShowExcel()
{
try
{
if (x == 0)
{
ex.Visible = true;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
finally
{
if (x == 0)
{
if (ws != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
if (wb != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
if (ex != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(ex);
GC.Collect();
}
}
}
}
解决方案:100分
excel对象模型不是线程安全的。虽然多线程工作的可能性是有的,但是强烈建议不这么做,会有很多问题。
在t1,t2启动前,要把线程设为STA:
t.SetApartmentState(System.Threading.ApartmentState.STA);
t.Start();
STA模式下,调用是顺序执行的,调用线程可能会阻塞一会,所以速度也会比较慢。
参考:http://msdn.microsoft.com/en-us/library/8sesy69e%28v=vs.100%29.aspx
在t1,t2启动前,要把线程设为STA:
t.SetApartmentState(System.Threading.ApartmentState.STA);
t.Start();
STA模式下,调用是顺序执行的,调用线程可能会阻塞一会,所以速度也会比较慢。
参考:http://msdn.microsoft.com/en-us/library/8sesy69e%28v=vs.100%29.aspx