2013-06-13 36 views
2

我有一個C#ListView與一些entrys,一個Methode刪除第一個條目和一個定時器來調用此方法。我的問題是,定時器工作正常(我檢查這與調用MessageBox)和刪除方法也很好(我通過調用此方法調用此按鈕,而不是定時器)。但計時器仍然不能從我的ListView中刪除項目。通過定時器C刪除ListView中的項目#

我的代碼:

void Button1Click(object sender, EventArgs e) 
    { 
     removeItems(); 
    } 

    private void timer_Tick(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     removeItems();  
    } 

    void removeItems() 
    { 
     MessageBox.Show("Hello from the removeMethod"); 
     listViewTeam.Items.RemoveAt(0); 
    } 

爲removeItems的兩個電話();讓messageBox出現,但只有Button也會刪除listView的第一個Item。

有人可以幫助ñ如何我可以通過計時器刪除第一個項目?

+0

作爲定時器您使用的? System.Timer或System.Windows.Forms.Timer?你有沒有在計時器上調用Start()方法?編輯:只是看到你使用系統計時器。使用其他人說的Winforms計時器,然後調用Start() –

回答

2

您使用的計時器不是線程安全的。而不是使用System.Timer,您應該使用System.Windows.Forms.Timer,因爲它會自動在UI線程上運行。那麼你的代碼將完美工作。

+0

「*您使用的計時器不是線程安全的*」 - 錯誤,您建議的計時器不是。 – James

+1

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx * System.Windows.Forms。計時器由此計時器類引發的計時器事件與您的Windows窗體應用程序中的其他代碼同步。任何駐留在定時器事件處理程序(對於此類定時器類)中的代碼都是使用應用程序的UI線程執行的。* 它對於Windows窗體應用程序來說是完全線程安全的。 – NibblyPig

+0

當使用單個UI線程時,它在Windows窗體應用程序中是線程安全的,是的。 'Forms.Timer'是專門爲單線程環境設計的,因此它不是線程安全的。例如,你不能在多線程環境中使用它。 [文檔](http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx)本身甚至聲明「* Windows窗體計時器組件是單線程的,並且僅限於精確度爲55毫秒如果您需要更高精度的多線程定時器,請使用System.Timers名稱空間中的Timer類。*「。 – James

1

您似乎在使用System.Timer這意味着您的Elapsed回調可能不一定會在UI線程上調用。你可以確保它通過使用Invoke

if (listViewTeam.InvokeRequired) 
{ 
    listViewTeam.Invoke((MethodDelegate)delegate { listViewTeam.Items.RemoveAt(0); }); 
} 

甚至更​​好,設置定時器SynchronizingObject屬性爲包含您ListView,你的代碼將只是工作形式。

+1

使用Forms定時器在UI線程上運行要簡單得多,但這是另一個解決方案來調用交叉線程。 – NibblyPig

+0

它更簡單,但不太準確 - 這一切都取決於計時器的用途以及它正在使用的上下文。 – James

-1

首先啓動計時器。但使用Windows Forms Timer.

你的設計師類:

partial class Form1 
{ 
    /// <summary> 
    /// Required designer variable. 
    /// </summary> 
    private System.ComponentModel.IContainer components = null; 

    /// <summary> 
    /// Clean up any resources being used. 
    /// </summary> 
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
    protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

    #region Windows Form Designer generated code 

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor. 
    /// </summary> 
    private void InitializeComponent() 
    { 
     this.components = new System.ComponentModel.Container(); 
     this.listBox1 = new System.Windows.Forms.ListBox(); 
     this.timer1 = new System.Windows.Forms.Timer(this.components); 
     this.SuspendLayout(); 
     // 
     // listBox1 
     // 
     this.listBox1.FormattingEnabled = true; 
     this.listBox1.Items.AddRange(new object[] { 
     "q", 
     "w", 
     "e", 
     "r", 
     "t", 
     "y", 
     "u", 
     "sfdgsdf", 
     "gf", 
     "gsd", 
     "fgs", 
     "dfg"}); 
     this.listBox1.Location = new System.Drawing.Point(170, 200); 
     this.listBox1.Name = "listBox1"; 
     this.listBox1.Size = new System.Drawing.Size(120, 95); 
     this.listBox1.TabIndex = 0; 
     // 
     // timer1 
     // 
     this.timer1.Tick += new System.EventHandler(this.timer1_Tick); 
     // 
     // Form1 
     // 
     this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
     this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
     this.ClientSize = new System.Drawing.Size(570, 502); 
     this.Controls.Add(this.listBox1); 
     this.Name = "Form1"; 
     this.Text = "Form1"; 
     this.Load += new System.EventHandler(this.Form1_Load); 
     this.ResumeLayout(false); 

    } 

    #endregion 

    private System.Windows.Forms.ListBox listBox1; 
    private System.Windows.Forms.Timer timer1; 
} 

你的窗體類:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void timer1_Tick(object sender, EventArgs e) 
    { 
     removeItems(); 
     if (listBox1.Items.Count == 0) 
     { 
      timer1.Stop(); 
     } 
    } 

    void removeItems() 
    { 
     MessageBox.Show("Hello from the removeMethod"); 
     listBox1.Items.RemoveAt(0); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     timer1.Start(); 
    } 
} 
0

你需要使用一個delegate安全地從後臺線程的UI控件交互(這是你在做什麼當你執行Timer時:

void Button1Click(object sender, EventArgs e) 
{ 
    removeItems(); 
} 

private void timer_Tick(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    removeItems();  
} 

void removeItems() 
{ 
    MessageBox.Show("Hello from the removeMethod"); 
    RemoveListViewItem(0); 
} 

public delegate void InvokeRemoveListViewItem(Int32 ItemIndex); 
public void RemoveListViewItem(Int32 ItemIndex) 
{ 
    if (InvokeRequired) 
    { 
     try { Invoke(new InvokeRemoveListViewItem(RemoveListViewItem), new Object[] { ItemIndex }); } 
     catch (Exception) 
     { 
      //react to the exception you've caught 
     } 
    } 

    listView.RemoveAt(ItemIndex); 
} 
0

就像SLC說你需要使用BeginInvoke。個人而言,我已經解決了它這樣的

public AddListItem myDelegate; 
0
       Windows.Forms  System.Timers   System.Threading 
Timer event runs on what thread? UI thread  UI or worker thread Worker thread 
Instances are thread safe?   No    Yes     No 
Familiar/intuitive object model? Yes   Yes     No 
Requires Windows Forms?    Yes   No     No 
Metronome-quality beat?    No    Yes*     Yes* 
Timer event supports state object? No    No     Yes 
Initial timer event schedulable? No    No     Yes 
Class supports inheritance?   Yes   Yes     No 

* Depending on the availability of system resources (for example, worker threads)