none
UI回應緩慢問題。 RRS feed

  • 問題

  • Dear all.

    新手小弟遇到一個問題,請問大家一個問題,

    我寫了一個程式,我用System.Timers.Timer再每0.2秒做輪詢問兩個模組的數值,存入datatable

    另外兩個System.Timers.Timr做0.4秒使MSChart重畫的動作,有事件再重畫中PostPaint用for迴圈改變Chart的顏色

    一個System.Timers.Timr跑兩分鐘透過serialPort問另外一組模組的狀態,

    groupBox做切換分頁,

    現在我只要程式開始執行,所有的UI變成超緩慢才會有回應,System.Timers.Timr還沒執行以及收集資料時,UI回應都算正常

    只要執行程式就會變自閉的程式,請問各位大大,遇到這種狀況有什麼方法可以讓UI反應變快,我有想過用多執行緒,可是我不知道可以加在哪裡,

    我很多都是用UI的事件觸發,不知道執行緒可以在哪個UI事件上使用。

    請問大家遇到這種問題都是以什麼方式解決的呢?

    請各位先進,高手們,給我個方向指引我吧~!!!!

    我的程式回應好慢,我都以為他死掉了.....

    2014年1月15日 上午 04:02

解答

  • Hi,

    你有在Elapsed這邊將它帶回主執行緒

    或是指定了SynchronizingObject?


    謙卑學習,持之以恆,才能不斷的Level Up

    • 已標示為解答 黑小胡 2014年1月16日 上午 01:48
    2014年1月15日 上午 06:01
  • 有可能是因為System.Timers.Timer 的間隔0.2秒太短了,

    而且你在時間觸發時做的事情所需的時間超過0.2秒

    導致下一次觸發Tick事件的時候 上一次的還沒有做完 ,就會變成搶UI的狀況,

    您試試看把Timer的觸發時間間隔條長一點試試看!

    2014年1月15日 下午 12:27
  • Hi,

    加了SynchronizingObject = this應該會把Elapsed事件帶回主執行緒

    你可以在那邊除錯並監看所在的執行緒為何

    沒加這段出錯應該是因為跨執行緒作業無效

    你在Elapsed事件那邊的處理除了詢問數值外

    應該還有做UI元件的操作吧

    只把這動作用BeginInvoke帶回主執行緒做就好了

    其它的動作還是讓它在別的執行緒上跑


    謙卑學習,持之以恆,才能不斷的Level Up

    • 已標示為解答 黑小胡 2014年1月16日 上午 01:48
    2014年1月15日 下午 02:28

所有回覆

  • 先看慢在哪,慢在撈資料可以用 thread 來撈。

    MSChart 在多緒的環境可參考:

    http://social.msdn.microsoft.com/Forums/vstudio/en-US/09135316-3867-405b-aae8-b1e2907281b9/poor-realtime-performance-of-the-mschart-control?forum=MSWinWebChart

    http://social.msdn.microsoft.com/Forums/vstudio/en-US/0cd8f71d-71eb-4331-a801-ddf8d28e8648/plot-serial-data-in-separate-thread?forum=vbgeneral


    強力監督SQL Injection問題!!

      • 小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
      • 雲端學堂Facebook: http://www.facebook.com/studyazure

    2014年1月15日 上午 04:27
    版主
  • 可使用BackgroundWorker  http://msdn.microsoft.com/zh-tw/library/system.componentmodel.backgroundworker(v=vs.110).aspx
    2014年1月15日 上午 05:17
  • Dear 小朱大大

    我測試把最前面System.Timers.Timer再每0.2秒做輪詢問兩個模組的數值<<這段拿掉

    沒資料時所有的UI反應都很快速,只要0.2秒做輪詢開始動作就變超慢的了。

    問題應該是出在這,只是我不了解的是,System.Timers.Timer不是就算是另外一個執行緒在跑嗎?

    這樣在new一個執行緒給他會不會太多執行緒呢?

    最後如果要加執行緒給他,是new再System.Timers.Timer的事件裡面、還是加在Form1裡面呢?

    感謝你回應~!!^^

    2014年1月15日 上午 05:36
  • 小胡:

    建議你可以直接弄一個Thread+Thread.Sleep方法,然後在裡邊死循環生成new,一旦生成之後通過某個自定義事件告知窗體重繪組件界面看看。


    ASP.NET Questions
    Other Discussions
    FreeRice Donate
    Issues to report
    Free Tech Books Search

    2014年1月15日 上午 05:47
  • Hi,

    你有在Elapsed這邊將它帶回主執行緒

    或是指定了SynchronizingObject?


    謙卑學習,持之以恆,才能不斷的Level Up

    • 已標示為解答 黑小胡 2014年1月16日 上午 01:48
    2014年1月15日 上午 06:01
  • Dear ThankfulHeart 大

    感謝你提供的方法,我會試試看的!

    Dear 蹂躪大

    我指定了.....this.lowdata.SynchronizingObject =this;

    是因為這段造成的UI回應緩慢的嗎?!

    沒加這段會有錯誤出現....Debug沒出現,點選exe就會出現錯誤~這是甚麼原因呢?

    2014年1月15日 上午 09:39
  • 有可能是因為System.Timers.Timer 的間隔0.2秒太短了,

    而且你在時間觸發時做的事情所需的時間超過0.2秒

    導致下一次觸發Tick事件的時候 上一次的還沒有做完 ,就會變成搶UI的狀況,

    您試試看把Timer的觸發時間間隔條長一點試試看!

    2014年1月15日 下午 12:27
  • Hi,

    加了SynchronizingObject = this應該會把Elapsed事件帶回主執行緒

    你可以在那邊除錯並監看所在的執行緒為何

    沒加這段出錯應該是因為跨執行緒作業無效

    你在Elapsed事件那邊的處理除了詢問數值外

    應該還有做UI元件的操作吧

    只把這動作用BeginInvoke帶回主執行緒做就好了

    其它的動作還是讓它在別的執行緒上跑


    謙卑學習,持之以恆,才能不斷的Level Up

    • 已標示為解答 黑小胡 2014年1月16日 上午 01:48
    2014年1月15日 下午 02:28
  • Dear SUKI Huang  & 蹂躪 大

    USER的需求,所以無法再延長Timer的時間,

    存取UI的部分我也有做委派的動作,只是我使用的是Invoke,蹂躪大說的BeginInvoke非同步我會試試看的

    只是之前因為委派不熟所以我才加上this.lowdata.SynchronizingObject =this;這行,因為加了就沒出現錯誤訊息(汗


    之後我有寫把錯誤訊息存入文字檔,錯誤訊息是

    System.InvalidOperationException: 集合已經修改; 列舉作業可能無法執行。

    我用Timer做資料新增到datatable的時候為了防止datatable被過度存取、新增、刪除

    有做copy到另外一個datatable,就是這一行有出錯,應該是copy沒完成,下一次的工作又開始了,

    現在我有加上Lock讓工作完成後才能做修改,我再試試看。

    感謝蹂躪大,一語驚醒夢中人阿!~

    感謝各位大大的技術支援,往後請大家多多指教,謝謝大家!



    • 已編輯 黑小胡 2014年1月16日 上午 01:49
    2014年1月16日 上午 01:46
  • Hi,

    我說的BeginInvoke主要是將動作帶回主執行緒,類似下面這樣

    public override void WriteLine(string message) { if (!m_ListBox.Visible) return; if (m_ListBox.InvokeRequired) { m_ListBox.BeginInvoke(new MethodInvoker( delegate { WriteLine(message); } )); return; } m_ListBox.Items.Add(string.Format("{0}\t{1}", DateTime.Now, message)); }

    不過你的錯誤貼出來後,看起來根本不用帶回主執行緒

    問題在資源競爭~Lock應該就好了...

    但慢的重點還是在你帶回到主執行緒了...

    另外你程式中應該要有些判斷處理

    像是問回來的值沒變的話不去更新

    或是將要更新的處理加進Queue內依序處理之類的

    甚至是還在處理更新時要暫停詢問


    謙卑學習,持之以恆,才能不斷的Level Up



    2014年1月16日 上午 02:19