winforms 如何使用C#在ETO应用程序上生成对UI线程的调用?

fiei3ece  于 2023-11-21  发布在  C#
关注(0)|答案(2)|浏览(168)

我想为linux和windows构建一个跨平台的GUI应用程序。ETO被推荐https://github.com/picoe/Eto我很习惯winforms,但我一直试图让ETO响应来自计时器的重复调用。我发现的例子需要使用winforms this. sockeRequired,这在Linux下不存在。
我想要一个定时器启动,并发送信号更新GUI文本框每100毫秒。
我有这个:

// This timer needs to kick off every 100ms to update the GUI.
Timer myTimer = new Timer(TimerTick, // the callback function
new object(),
0,
100); // Every 100ms

private static void TimerTick(object state)
{
    if (ProcessTics == true)
    { Task.Factory.StartNew(CallTheBackgroundFunctions); }

}

private static void CallTheBackgroundFunctions()
{
    OtherClass.ProcessTic();
    mainTextDisplay.Text = OtherClass.GetText(); //This errors out
}

字符串
问题是计时器是一个静态示例,而我已经把我的类写成了一个静态示例。如果我提供了一个对主窗体的引用,这个.Invalidate();不会更新gui。
我相信我需要使用ETO的调用,但我真的很难让它工作。
有没有什么建议可以让后台线程更新ETO表单上的GUI?或者是其他支持C#的跨平台GUI框架?这些都是针对文本处理项目的。
感谢您抽出宝贵的时间。

y3bcpkx1

y3bcpkx11#

要调用UI线程上的方法,请使用Eto.Forms.Application.Instance.Invoke()Eto.Forms.Application.Instance.AsyncInvoke()。后者将调度调用并立即返回。
或者,对于这种类型的场景,您也可以使用Eto.Forms.UITimer,它在主循环上调度其事件。

jgovgodb

jgovgodb2#

真实的技巧是正确地调用Application.Instance.Delegate。
如果其他人遇到类似的问题,这里是我如何安排类从另一个线程更新文本框。

public static class TextRender
{   
    public delegate void BroadCastText(object sender, EventArgs e, string message);
    public static BroadCastText Broadcasting;


    public static void ProcessTic()
    {       
        string outboundText = "";
        // do some behind the scenes work.

        if (Broadcasting != null) // Verify someone has subscribed to the event, otherwise null object error.
        {
            Broadcasting(null, EventArgs.Empty, outboundText);
        }
        else
        {
            Console.WriteLine("I'm talking but no one is listening!!");
        }
    }
}

public class MainForm : Form
{
    Timer myTimer; // High resolution timer.
    UITimer UITimerTick = new UITimer(); // Low resolution timer, but runs on the UI thread.
    TextArea mainTextDisplay = new TextArea(); // Textbox that needs to be updated in realtime.
    

    
   private static void TimerTick(object state)
   {
       TextRender.ProcessTic();
   }

   /// <summary>
   /// Takes the incoming string and uses the UI thread to update the display.
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   /// <param name="message"></param>
   private void WriteTextDelegate(Object sender, EventArgs e, string message)
   {
       Application.Instance.Invoke(delegate {
           mainTextDisplay.Text = message;
       });
   }

   /// <summary>
   /// Toggles a timer that performs a callback to update the UI.
   /// </summary>
   private void Timer1()
   {
       if (Timer1Active)
       {
           TextRender.Broadcasting -= WriteTextDelegate;
           myTimer.Dispose();
           Timer1Active = false;
       }
       else
       {
           myTimer = new Timer(TimerTick, // the callback function
           new object(), 
           0, // the time to wait before the timer starts it's first tick
           50); // the tick interval

           TextRender.Broadcasting += WriteTextDelegate;  //  Subscribe to the event
           Timer1Active = true;
           Console.WriteLine("Timer 1 start");
       }
   }

   /// <summary>
   /// Toggles using the UI timer solution.  This is not intended to update faster than 1 per second.  
   /// </summary>
   private void Timer2()
   {
       if (Timer2Active)
       {
           UITimerTick.Stop();
           UITimerTick.Dispose();
           Timer2Active = false;
       }
       else
       {
           UITimerTick.Interval = 0.5;  //half second refresh.  Can't go any faster without window freezing.
           UITimerTick.Elapsed += (sender, ev) =>
           {
               TextRender.ProcessTic();
               mainTextDisplay.Text = TextRender.CachedText;
           };
           
           UITimerTick.Start();
           Timer2Active = true;
           Console.WriteLine("Timer 2 start.");
       }
   }

}

字符串

相关问题