我现在已经解决了6个小时的问题了,但我仍然无法弄明白。我希望你能帮助我。
我正在开发一个与Crystal-Report-Engine(SAP,.NET Framework 4.0上的最新版本,32位C#应用程序)有关的项目。基本上,它的工作原理如下:
我正在打开我的Main-Form,它动态地显示特定报告文件(.rpt)的所有参数。输入我的参数值后,应用程序正在进行一些语法检查并将参数传递给ReportDocument。
问题:现在我正在创建一个新的ReportForm(我自己的类),它是一个带有CrystalReportViewer的Windows.Form派生类。 ReportForm使用传递的参数将crystalReportViewer-Object的ReportSource设置为先前创建的ReportDocument。 - >当表单显示时,Crystal Report Viewer正在加载。
问题#1:我仍然希望能够在Crystal Report Viewer加载报告时访问我的主表单(有时这可能需要大约5-6分钟) - 例如,创建一些其他报告报告仍在加载中。这是唯一可能的,如果我为这个新表单创建一个线程 - 但是这(有时)会导致一个ContextSwitchDeadlock,因为我必须创建一个新的Thread,它正在创建一个新的GUI-Control(ReportForm)。
问题2:如果我没有创建新的Thread并以myNewReportForm.Show()为例启动新的ReportForm,那么我必须等到报告加载后才能访问我的Main-表格(直到报告完全加载)。下一个问题是我无法关闭/退出/杀死我的应用程序,因为线程仍在加载报告 - 我还必须等待,直到加载报告。但我想能够随时关闭应用程序(Main-Form AND所有ReportForms)
它基本上看起来像那样(短版):
/* pass parameters to reportDocument */
ReportForm reportForm = new ReportForm(reportDocument);
reportForm.Show();
在ReportForm中:
crystalReportViewer.ReportSource = this.reportDocument;
你有什么想法吗?
最佳, Cylence
答案 0 :(得分:1)
终于解决了这个问题。所以这是我的解决方案:
为每个为Crystal Report Viewer创建新线程的人:小心!
以下是一般解决方案:
/* In Main Form */
/*...*/
ThreadStart threadStart = delegate() { reportThreadFunction(reportDocument); };
Thread reportThread = new Thread(threadStart);
/* Setting the ApartmentState to STA is very important! */
reportThread.SetApartmentState(ApartmentState.STA);
reportThread.Start();
}
/* ... */
private void reportThreadFunction(ReportDocument reportDocument)
{
ReportThread rt = new ReportThread(reportDocument);
newReportForm = rt.Run();
Application.Run(newReportForm);
newReportForm.Show();
}
/* Class ReportThread */
public class ReportThread
{
ReportDocument reportDocument;
CrystalReportViewer crv;
Template template;
public ReportThread(ReportDocument reportDocument)
{
this.reportDocument = reportDocument;
}
public ReportForm Run()
{
ReportForm rf = new ReportForm(reportDocument);
return rf;
}
}
最佳, Cylence
答案 1 :(得分:0)
谢谢! 这个决心对我来说!
仅为简化上述代码:
/* In Main Form */
/*...*/
ThreadStart threadStart = delegate({reportThreadFunction(reportDocument);};
Thread reportThread = new Thread(threadStart);
/* Setting the ApartmentState to STA is very important! */
reportThread.SetApartmentState(ApartmentState.STA);
reportThread.Start();
}
private void reportThreadFunction(ReportDocument reportDocument)
{
//Create and Start the form
Application.Run(new ReportThread(reportDocument));
}
/* Class ReportThread */
/* A form whith a CrystalReportViewer inside*/
public partial class ReportThread : Form
{
public CrystalReportViewer crv; //initiated in partial class off form
public ReportThread(ReportDocument reportDocument)
{
InitializeComponent();
CrystalReportViewer.ReportSource = reportDocument;
}
}