【问题标题】:Access statusbar on form from cplex callback function c#从 cplex 回调函数 c# 访问表单上的状态栏
【发布时间】:2016-10-25 09:50:50
【问题描述】:

我正在使用 C# .Net 应用程序,该应用程序使用 Cplex DLL 进行优化操作,并且在该操作期间,我想将状态进度写入启动操作的状态栏。

这是具体表格的大体布局;

namespace ActResMain
{
    public class FormOptimize : System.Windows.Forms.Form
    {
        private callCplex()
        {
            //...
            cplex.Use(new Cplex_ContinuousCallback());
            cplex.Solve()
        }
        public void Update_OptimizeStatusbarPanel(String strText)
        {
                statusBarPanel_1.Text = strText;
                statusBar1.Refresh();
        }
        internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
        {
            FormOptimize formOpt = new FormOptimize();
            public override void Main()
            {
                //From here I want to edit the statusbar at FormOptimize. I can write progress to console without any problems, but cannot reach function "Update_OptimizeStatusbarPanel".
                //If I include "FormOptimize formOpt = new FormOptimize" here, i get Visual studio exception on illegal window reference.
            }
        }

    }
}

我也尝试过像这样调用 Update_OptimizeStatusbarPanel 函数:

internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
            {
                FormOptimize formOpt = new FormOptimize();
                public override void Main()
                {
                    FormCollection fc = Application.OpenForms;
                    var mpc = fc[1];
                    Type type = mpc.GetType(); 
                    MethodInfo dynMethod = type.GetMethod("Update_OptimizeStatusbarPanel");
                    dynMethod.Invoke(mpc, new object[] { String.Format("Running Optimization: {0} iterations ", Niterations)});
                }
            }

但是我从 Visual Studio 得到一个异常,指出一个线程创建的对象不能从另一个线程修改。

也许这是我错过的一些愚蠢的事情,但非常感谢您的帮助

编辑:我根据 Mohammad Dehghans 的建议编辑了代码,

public class FormOptimize : System.Windows.Forms.Form
{
    private callCplex()
    {
        cplex.Use(new Cplex_ContinuousCallback(this));
        cplex.Solve()
    }

    internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
    {
        FormOptimize _formOptimize;
        public Cplex_ContinuousCallback(FormOptimize formOptimize)
        {
            this._formOptimize = formOptimize;
        }

        public override void Main()
        {
            if (Niterations % 10 == 0)
            {
                _formOptimize.Update_OptimizeStatusbarPanel(0, String.Format("Running Optimization: {0} iterations ", Niterations), 0);
            }
        }
    }

    public void Update_OptimizeStatusbarPanel(short panelIndex, String strText, short severity)
    {
        if (statusBar1.InvokeRequired)
            statusBar1.Invoke(new Action<short, string, short>(Update_OptimizeStatusbarPanel), panelIndex, strText, severity);
        else
        {
            if (panelIndex == 0)
            {
                //...
                statusBarPanel_0.Text = strText;
            }
            else if (panelIndex == 1)
            {
                //...
                statusBarPanel_1.Text = strText;

            }
            statusBar1.Refresh();
        }
    }
}

但是这样做我显然破坏了一些东西,因为应用程序只是在第一次调用 statusBar1.Invoke() 之后 ..stops 。如果我暂停调试器,它会说 cplex.Solve() 正在执行,但没有任何反应。

【问题讨论】:

    标签: c# .net callback cplex


    【解决方案1】:

    首先,您需要将表单实例传递给实现的回调类,因此当调用Main 方法时,您可以访问屏幕上显示的确切实例。

    其次,您需要使用Invoke 方法从另一个线程更新 UI 控件(到目前为止,我还没有使用过 CPLEX,但我猜回调是从另一个线程调用的。这很常见)。 Read this for more information.

    完整的代码可以是:

    public class FormOptimize : System.Windows.Forms.Form
    {
        private callCplex()
        {
            //Misc code
            cplex.Use(new Cplex_ContinuousCallback(this)); // <-- passing `this`
            cplex.Solve()
            //Misc code
        }
    
        public void Update_OptimizeStatusbarPanel(String strText)
        {
            if (statusBarPanel_1.InvokeRequired)
                statusBarPanel_1.Invoke(Action<string>(Update_OptimizeStatusbarPanel), strText);
            else
            {
                statusBarPanel_1.Text = strText;
                statusBar1.Refresh();
            }
        }
    
        internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
        {
            FormOptimize _formOptimize;
            public Cplex_ContinuousCallback(FormOptimize formOptimize)
            {
                this._formOptimize = formOptimize;
            }
    
            public override void Main()
            {
                //...
                _formOptimize.Update_OptimizeStatusbarPanel(String.Format("Running Optimization: {0} iterations ", Niterations));
            }
        }
    }
    

    【讨论】:

    • 似乎它既解决了问题又创造了另一个问题。现在应用程序在调用 statusbar1.Invoke 后似乎停止了一些事情。我用我对你答案的解释更新了我的问题。是否实施了不正确的事情?
    猜你喜欢
    • 1970-01-01
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 2018-01-08
    • 1970-01-01
    • 2020-01-10
    相关资源
    最近更新 更多