.NET Scheduled Timer - 跨线程操作无效

时间:2017-05-17 16:36:46

标签: c# multithreading

我正在使用计划计时器www.codeproject.com

但是,在使用listview时,我收到了以下错误:

跨线程操作无效:控制'lsViewIm'从其创建的线程以外的线程访问。

这是我的代码: 这是我的按钮执行计时器:

delegate void TickHandler(string Profile);
private void btnStart_Click(object sender, EventArgs e)
{
    Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);  

    if(ConfigurationManager.AppSettings.AllKeys.Contains("Stock-Enable"))
    {
        if (config.AppSettings.Settings["Stock-Enable"].Value.ToString() == "Y")
        {
            main.oWriteText(lsViewIm, "Reading... " + DateTime.Now.ToString(), Color.Black, false, "logs"); 

            IScheduledItem Item = GetSchedStock();
            _AlarmTimer.Stop();
            _AlarmTimer.ClearJobs();
            _AlarmTimer.AddJob(Item, new TickHandler(updateStocks), "Woo1");
            _AlarmTimer.Start();
        }
    }
}

private ScheduleTimer _AlarmTimer = new ScheduleTimer();
private IScheduledItem GetSchedStock()
{
    return new ScheduledTime("ByMinute", "1"); 
}

此代码将向ListView显示详细信息:

public void oWriteText(ListView lsView, string txt, Color? oColor = null, Boolean isStored = false, string oFile = "logs")
{
    ListViewItem addItem = lsView.Items.Add(txt);
    lsView.EnsureVisible(lsView.Items.Count - 1);
    addItem.SubItems[0].ForeColor = oColor ?? Color.Black;
    lsView.Refresh(); 
}

这是我的方法,这里将把剩下的代码放在这里。

public void updateStocks(string Profile)
{
    oWriteText(lsViewIm, DateTime.Now.ToString(), Color.Black, false, "logs");
    return;
}

1 个答案:

答案 0 :(得分:1)

谢谢!

自:

    //ListViewItem addItem = lsView.Items.Add(txt);
    //lsView.EnsureVisible(lsView.Items.Count - 1);
    //addItem.SubItems[0].ForeColor = oColor ?? Color.Black;
    //lsView.Refresh(); 

要:

    ListViewItem addItem = null;
    ControlInvoke(lsView, () => addItem = lsView.Items.Add(txt));
    ControlInvoke(lsView, () => addItem.SubItems[0].ForeColor = oColor ?? Color.Black);
    ControlInvoke(lsView, () => lsView.EnsureVisible(lsView.Items.Count - 1));
    ControlInvoke(lsView, () => lsView.Refresh());
delegate void UniversalVoidDelegate(); 
public static void ControlInvoke(Control control, Action function)
{
    if (control.IsDisposed || control.Disposing)
        return;

    if (control.InvokeRequired)
    {
        control.Invoke(new UniversalVoidDelegate(() => ControlInvoke(control, function)));
        return;
    }
    function();
}