【问题标题】:C# Creating/Closing Multiple Forms (Threads) - Crystal Report ViewerC# 创建/关闭多个表单(线程) - Crystal Report Viewer
【发布时间】:2014-10-07 12:54:02
【问题描述】:

我已经解决了一个问题 6 个小时,但我仍然无法弄清楚。我希望你能帮助我。

我正在处理一个与 Crystal-Report-Engine 相关的项目(SAP,.NET Framework 4.0 上的最新版本,32 位 C# 应用程序)。基本上,它是这样工作的:

我正在打开我的主窗体,它会动态地向我显示特定报告文件 (.rpt) 的所有参数。输入我的参数值后,应用程序会进行一些语法检查并将参数传递给 ReportDocument。

问题:现在我正在创建一个新的 ReportForm(我自己的类),它是带有 CrystalReportViewer 的 Windows.Form 的派生类。 ReportForm 使用传递的参数将 CrystalReportViewer-Object 的 ReportSource 设置为先前创建的 ReportDocument。 -> Crystal Report Viewer 正在加载,当表单出现时。

问题 #1:我仍然希望能够在 Crystal Report Viewer 加载报表时访问我的主窗体(有时这可能需要大约 5-6 分钟) - 例如,在之前创建一些其他报表时报告仍在加载中。这只有在我为这个新表单创建一个线程时才有可能——但这(有时)会导致 ContextSwitchDeadlock,因为我必须创建一个新线程,它正在创建一个新的 GUI-Control(ReportForm)。

问题 #2:如果我不创建新线程并启动新的 ReportForm,例如使用 myNewReportForm.Show(),那么我必须等到报告加载完毕并且无法访问我的 Main-表单(直到报表完全加载)。下一个问题是我无法关闭/退出/杀死我的应用程序,因为线程仍在加载报告 - 我还必须等待,直到加载报告。但我希望能够随时关闭应用程序(主窗体和所有报表窗体)

基本上是这样的(短版):

/* pass parameters to reportDocument */
ReportForm reportForm = new ReportForm(reportDocument);
reportForm.Show();

在报告表单中:

crystalReportViewer.ReportSource = this.reportDocument;

你有什么想法吗?

最好, 赛伦斯

【问题讨论】:

  • 你应该修正你的报告。加载报告不应花费 5-6 分钟。您在报告中提取和显示了多少数据?您如何在表单加载或按钮单击中打开myNewReportForm.Show()
  • 感谢您的回答。该报告通常不会花费那么长时间...但是查看器仍有可能遇到超时(例如,数据库连接信息不再存在/错误) - 我想确保在这种情况下,用户仍然可以工作(返回主窗体并在报告超时运行时开始另一个报告)或者用户可以关闭应用程序。在传递参数并创建新的 ReportForm(ReportDocument)-Object 后,我​​在 Main-Form 中使用按钮打开 myNewReportForm.Show()。
  • 那么在这种情况下,我建议您在主表单的表单加载中打开myNewReportForm.Show()。这样,当您打开 formload 时,它会打开该表单并让它运行,您仍然可以在主表单中工作。
  • 好主意,但这并没有真正的帮助,因为表单是动态创建的 - 取决于用户在运行时想要拥有多少报告。下一个问题是,当reportViewer 在表单中加载时,我将无法在主表单中工作。

标签: c# multithreading forms crystal-reports report


【解决方案1】:

终于解决了问题。所以这是我的解决方案:

对于为 Crystal Report Viewer 创建新线程的每个人:小心!

Problem solving - SAP

这是一个通用的解决方案:

/* 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;
    }
}

最好, 赛伦斯

【讨论】:

    【解决方案2】:

    谢谢! 这是我的决心!

    只是为了简化上面的代码:

     /* 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;
         }
     }
    

    【讨论】:

      猜你喜欢
      • 2023-03-19
      • 2016-04-09
      • 1970-01-01
      • 2012-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多