我想我已经阅读了这里和MSDN上的每一篇文章,但我认为我是一个特例,因为大多数文章和帖子似乎都没有涵盖我正在尝试做的事情。
我正在浏览Excel工作表并提取记录并将其传递出去,以便将它们转换为不同的文件类型。我正在尝试使用线程,所以我没有占用UI,一切都很好,除了更新我在表单中的进度条。以下是需要更新表单的类:
public class ExcelItem : Form1
{
private string inFile { get; set; }
public ExcelItem(string file)
{
inFile = file;
}
public string getExcelData()
{
string result = "";
int numRec = 0;
int recCount = 0;
Excel.Application xlApplication;
Excel.Workbook xlWorkbook;
Excel.Worksheet xlWorksheet;
Excel.Range xlRange;
xlApplication = new Excel.Application();
xlWorkbook = xlApplication.Workbooks.Open(File, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorksheet = (Excel.Worksheet)xlWorkbook.Worksheets.get_Item(2);
xlRange = xlWorksheet.UsedRange;
int rCnt = xlRange.Rows.Count;
int cCnt = xlRange.Columns.Count;
//for (int k = 1; k <= xlWorkbook.Worksheets.Count; k++)
// MessageBox.Show("Found worksheet " + k);
// get the number of records in tne sheet and use numRec to set progress bar max
for (int i = 1; i <= xlRange.Rows.Count; i++)
{
for (int j = 1; j <= xlRange.Columns.Count; j++)
{
if ((((Excel.Range)xlWorksheet.Cells[i, j]).Value2 != null) && (((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() == "Date of Birth"))
{
numRec++;
//code for updating progress bar max would go here
}
}
}
// iterate through records in sheet, use recCount to set progress bar value and return records
for (int i = 1; i <= xlRange.Rows.Count; i++)
{
for (int j = 1; j <= xlRange.Columns.Count; j++)
{
if ((((Excel.Range)xlWorksheet.Cells[i, j]).Value2 != null) && (((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() == "Date of Birth"))
{
result += Environment.NewLine;
recCount++;
// code for updating progress bar value would go here
}
if ((((Excel.Range)xlWorksheet.Cells[i,j]).Value2 != null) && (((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() != ":"))
{
result += (string)((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() + Environment.NewLine;
}
}
}
return result;
}
}
}
返回记录不是问题,只是更新进度条之类的东西现在很头疼。到目前为止,我已经尝试过代理,后台工作,BeginInvoker和线程,但似乎无法获得任何工作。提前感谢您的帮助。
答案 0 :(得分:1)
在WinForms中,您需要运行Invoke方法,以更新另一个Control
中的Thread
。
答案 1 :(得分:0)
我找到了另一种方法,使用位于需要包含的System.Runtime.Remoting.Messaging中的AsyncCallBack来解决这个问题。以下是我最终做的事情:
AsyncCallBack方法(pbvalue是一个私有全局变量):
public void setPg1InAnotherThread(Int32 val)
{
new Func<Int32>(setPbValue).BeginInvoke(new AsyncCallback(setPbValueCallback), null);
}
private Int32 setPbValue()
{
Int32 result = recCount;
return result;
}
private void setPbValueCallback(IAsyncResult ar)
{
AsyncResult result = (AsyncResult)ar;
Func<Int32> del = (Func<Int32>)result.AsyncDelegate;
try
{
Int32 pbValue = del.EndInvoke(ar);
if (pbValue != 0)
{
Form1 frm1 = (Form1)findOpenForm(typeof(Form1));
if (frm1 != null)
{
frm1.setPbValue(pbValue);
}
}
}
catch { }
}
唯一剩下的就是获取对主表单的引用,这是我无法通过文件处理程序或委托来完成的,因为我是a)在一个单独的线程中而b)在一个单独的类中。
private static Form findOpenForm(Type typ)
{
for (int i = 0; i < Application.OpenForms.Count; i++)
{
if (!Application.OpenForms[i].IsDisposed && (Application.OpenForms[i].GetType() == typ))
{
return Application.OpenForms[i];
}
}
return null;
}
使用这些方法,只需要使用您需要的任何值调用setPg1InAnotherThread()。我也可能会回去并将Int32重构为Int16。这不是首选的方法,BackGroundWorker或通常的委托方法应尽可能使用,但适用于我的情况。