2016-10-25 6 views
0

Cplex DLL을 최적화 작업에 사용하는 C# .Net 응용 프로그램과 함께 작업하고 있는데이 작업 중에 작업을 시작한 상태 표시 줄에 상태 진행률을 쓰려고합니다. .cplex 콜백 함수에서 양식의 상태 표시 줄 액세스 # C#

이것은 특정 양식의 일반적인 레이아웃입니다.

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)}); 
       } 
      } 

을하지만 나는 하나 개의 스레드에서 만든 개체가 다른 스레드에서 수정 될 수 없다는 비주얼 스튜디오에서 예외가 :

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 함수를 호출 노력했다.

은 어쩌면 내가 놓친 것이 멍청한 짓이지만, 도움을 크게

편집을 appriciated입니다 : 내가 모하마드 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()를 호출 한 후 응용 프로그램이 중지 될 때 처음으로 호출됩니다. 디버거를 일시 중지하면 cplex.Solve()가 실행 중이지만 더 이상 아무 것도 발생하지 않는다고 표시됩니다.

답변

0

우선 양식의 인스턴스를 구현 된 콜백 클래스에 전달해야합니다. 따라서 Main 메서드가 호출되면 화면에 표시되는 정확한 인스턴스에 액세스 할 수 있습니다.

두 번째로 다른 스레드에서 UI 컨트롤을 업데이트하려면 Invoke 메서드를 사용해야합니다 (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)); 
     } 
    } 
} 
+0

보인다. 이제 응용 프로그램은 statusbar1.Invoke를 호출 한 후 무언가를 중단 한 것으로 보입니다. 귀하의 대답에 대한 제 해석으로 제 질문을 업데이트했습니다. 잘못된 것을 구현 했습니까? –