使用自动重置事件无法按预期工作

时间:2015-06-04 14:27:28

标签: c# winforms .net-4.5

我对c#编程很陌生,我试图达到以下结果,但没有这样做。

我的期望 - : 在按钮的单击事件中,我想通过其API打开应用程序,运行分析,然后退出应用程序。在运行应用程序时,我在表单上有一个进度条,它应该从0到100继续,直到通过API调用的RunAnalysis()方法执行,执行时进度条应该显示为100%和应用程序呼叫应该退出

发生了什么 - :

正在执行RunanAlysis()并且应用程序退出,按钮的单击事件被执行,然后进度条从0到100移动,这不应该发生

我的尝试是什么

namespace trialapp
{
    public partial class Form1 : Form
    {
        AutoResetEvent obj = new AutoResetEvent(false);

        public Form1()
        {
            InitializeComponent();
        }

        ETABS2015.cSapModel SapModel;
        System.Reflection.Assembly ETABSAssembly;
        ETABS2015.cOAPI ETABSObject;
        int result = -1;
        delegate int MyDelegate();
        MyDelegate pointer = null;

        private void button1_Click(object sender, EventArgs e)
        {
            //Use ret to check return values of OAPI calls 
            int ret;

            //Dynamically load ETABS.exe assembly from the program installation folder 
            string pathToETABS = System.IO.Path.Combine(Environment.GetEnvironmentVariable("PROGRAMFILES"), "Computers and Structures", "ETABS 2013", "ETABS.exe");
            ETABSAssembly = System.Reflection.Assembly.LoadFrom(pathToETABS);

            //Create an instance of ETABSObject and get a reference to cOAPI interface
            ETABSObject = (ETABS2015.cOAPI)ETABSAssembly.CreateInstance("CSI.ETABS.API.ETABSObject");

            //Start ETABS application
            ret = ETABSObject.ApplicationStart();

            //Get a reference to cSapModel to access all OAPI classes and functions
            SapModel = ETABSObject.SapModel;

            //Initialize model
            ret = SapModel.InitializeNewModel();

            //Create steel deck template model
            ret = SapModel.File.NewSteelDeck(4, 12, 12, 4, 4, 24, 24);

            //Save model
            System.IO.Directory.CreateDirectory("C:\\ETABSAPI");
            ret = SapModel.File.Save("C:\\ETABSAPI\\example2.edb");

            //Run analysis
            backgroundWorker1.RunWorkerAsync();
           // ret = SapModel.Analyze.RunAnalysis();


            obj.WaitOne();

            //Close ETABS
            ret = ETABSObject.ApplicationExit(false);

            //Clean up variables
            SapModel = null;
            ETABSObject = null;

            //Check ret value 
            if (ret == 0)
            {
                MessageBox.Show("API script completed succesfully.");
            }
            else
            {
                MessageBox.Show("API script FAILED to complete.");
            }

        }

        public void AfterRunAnalysisComplete(IAsyncResult resultHolder)
        {
            result = pointer.EndInvoke(resultHolder);

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            pointer = new MyDelegate(SapModel.Analyze.RunAnalysis);

            IAsyncResult flag = pointer.BeginInvoke(new AsyncCallback(AfterRunAnalysisComplete), null);

            while (!flag.IsCompleted)
            {
                for (int i = 0; i <= 100; i++)
                {

                    Thread.Sleep(100);
                    backgroundWorker1.ReportProgress(i);
                    if (i == 100)
                    {
                        i = 0;
                    }
                    if (flag.IsCompleted)
                    {
                        break;
                    }
                }
            }

            backgroundWorker1.ReportProgress(100);
            //obj.Set();


        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }
    }
}

任何人都可以告诉我出错的地方吗?

修改 - :

我尝试不使用WaitOne()并在backgroundWorker1.RunWorkerAsync();方法中放置backgroundWorker1_DoWork后面的代码,但这不是我想做的,因为主要项目的范围太大而且这对于类的设计没有意义。

1 个答案:

答案 0 :(得分:0)

正如我所看到的那样,问题在于你何时开始

ret = ETABSObject.ApplicationStart();

它将在一个新程序中启动它,您的程序将无法访问该程序。我建议在TaskFactory中启动应用程序,然后您可以使用一段时间来检查任务是否仍在运行并更新进度条。

也许是这样的:

var etabApp = Task.Factory.Startnew(() => { ETABSObject.ApplicationStart()});

while(etabApp.Status == TaskStatus.Running)
{
   //Do something to check the percent complete and update the progress bar
}