2013-03-03 32 views
-2

我正在開發一個應用程序,它將主動從文件中讀取並實時分析和顯示該文件中的信息到UI。如何使用線程實時更新UI

我讀過的一切都告訴我我應該使用某種線程來做到這一點。我已經探索過後臺工作人員,並嘗試在運行時創建一個單獨的線程,並使用該線程更新所有UI元素。

當我不能(或不應該)進行交叉線程調用時,問題就出現了,因爲原始UI元素是在不同的線程上創建的。

有沒有辦法在線程上創建這些UI元素來更新它們?做這個的最好方式是什麼?

編輯:有一個回覆這篇文章(現在已經消失)解釋我應該如何做到這一點。在使用描述的方法更新我的代碼之後 這是我用過的更新過的代碼。一切都很好,直到我加入文件系統觀察者。只要我補充一點,我得到了關於不進行交叉線程調用的相同錯誤。

會議是I類通過創建日誌文件

private Session s1 = new Session(""); 
private FileSystemWatcher fsw; 
private OpenFileDialog ofd1 = new OpenFileDialog(); 

private BackgroundWorker bgw; 

private bool logActive = false; 

public frmMain() 
{ 
    InitializeComponent(); 
    bgw = new BackgroundWorker(); 
    bgw.WorkerReportsProgress = true; 
    bgw.ProgressChanged += HandleProgressChanged; 
    bgw.DoWork += HandleDoWork; 

    fsw = new FileSystemWatcher(@"H:\Logs", "*.txt"); 
    fsw.SynchronizingObject = this; 
    fsw.IncludeSubdirectories = false; 
    fsw.EnableRaisingEvents = true; 
    fsw.NotifyFilter = NotifyFilters.Size; 
    fsw.Changed += new FileSystemEventHandler(fsw_OnChanged); 
} 

private void frmMain_Load(object sender, EventArgs e) 
{ 
    ofd1.Filter = "log files (*.txt)|*.txt|All files (*.*)|*.*"; 
    ofd1.FilterIndex = 2; 
    ofd1.RestoreDirectory = true; 
} 

private void fsw_OnChanged(object source, System.IO.FileSystemEventArgs e) 
{ 
    bgw.RunWorkerAsync(); 
} 

// this runs on the UI thread 
// here's where you update the UI based on the information from the event args 
private void HandleProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    for (int i = s1.previousLineNumber; i < s1.GetMessageCount(); i++) 
    { 
     ListViewItem lvi = new ListViewItem((s1.GetMessage(i).date).ToString()); 
     lvi.SubItems.Add(s1.GetMessage(i).type.ToString()); 
     lvi.SubItems.Add(s1.GetMessage(i).data); 
     listView1.Items.Add(lvi); 
    } 
} 

// this runs on a background thread; you cannot modify UI controls here 
private void HandleDoWork(object sender, DoWorkEventArgs e) 
{ 
    s1.ParseLiveFile(); 
    bgw.ReportProgress(100); 
} 
+0

最好的方法是使用委託來訪問主線程conrols。這很容易,並在stackoverflow上多次描述。搜索一下,我相信你會找到有用的答案。 – 2013-03-03 21:13:30

+1

您的方法存在一個基本缺陷:您可以從其他線程操縱UI,並在「前臺」線程中執行實際的工作/邏輯(例如數據分析)。但是,大多數UI框架只需要相反的內容:在後臺線程中執行該工作,並從單個前臺線程(「UI線程」)更新UI。 – stakx 2013-03-03 21:16:44

+0

不幸的是,這已經超出了我的直接知識領域,但我可以告訴你解決方案的大致方向:使用衆多線程池庫中的一個爲每次文件系統更改啓動任務。這些線程將根據文件信息構建數據結構,然後通過延續將數據返回到UI線程,然後UI線程可以填充控件。 – siride 2013-03-04 00:01:33

回答

0

,它分析爲了更新你應該使用調用或BeginInvoke的UI。

void LengthyProcessInThread() 
{ 
    ... 
    foreach(var item in file) 
    { 
     Invoke(delegate() { 
      .. Update UI here. 
     }); 
    } 
} 

Invoke是控件上的方法,例如:包含UI的表單。

祝你好運。