【问题标题】:C# Windows Form application Error : "Cross-thread operation not valid." [duplicate]C# Windows 窗体应用程序错误:“跨线程操作无效。” [复制]
【发布时间】:2013-08-16 17:06:47
【问题描述】:

我正在尝试用 C# 构建一个简单的 Windows 窗体应用程序。其中lblIPAddress显示我的本地IP地址,lblInfo显示我的IP地址的最后更新时间。btnRefresh用于刷新数据。但是一旦tickTimer_Elapsed 事件被触发,它就会抛出错误“跨线程操作无效:控制'lblInfo' 从创建它的线程以外的线程访问。”

请提出建议。我的完整代码如下所示:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using Time = System.Timers;
using Connect = System.Net.NetworkInformation.NetworkInterface;

namespace ShowMyIP
{
    public class UpdatedInfo
    {
        public string lastUpdate = string.Empty;
        public string localIP = string.Empty;
    }
    public partial class ShowLocalIP : Form
    {
        UpdatedInfo updatedIP;
        public static Time.Timer tickTimer = new Time.Timer();
        public const int INTERVAL = 60 * 1000;

        public ShowLocalIP()
        {
            InitializeComponent();
            InitializeTimer();

            updatedIP = new UpdatedInfo();
            updatedIP = GetLocalIP(updatedIP);
            lblIPAddress.Text = updatedIP.localIP;
            lblInfo.Text = updatedIP.lastUpdate;             
        }
        public void InitializeTimer()
        {
            tickTimer.Interval = INTERVAL;
            tickTimer.Enabled = true;
            tickTimer.Elapsed += new Time.ElapsedEventHandler(tickTimer_Elapsed);
            tickTimer.Start();
            GC.KeepAlive(tickTimer);
        }

        private void tickTimer_Elapsed(object sender, Time.ElapsedEventArgs e)
        {
            updatedIP = new UpdatedInfo();
            updatedIP = GetLocalIP(updatedIP);
            lblIPAddress.Text = updatedIP.localIP;
            lblInfo.Text = updatedIP.lastUpdate;           
            tickTimer.Interval = INTERVAL;
            tickTimer.Enabled = true;
            tickTimer.Start();
            GC.KeepAlive(tickTimer);
        }

        private UpdatedInfo GetLocalIP(UpdatedInfo UpdatedIP)
        {
            if (Connect.GetIsNetworkAvailable())
            {
                IPHostEntry host;
                host = Dns.GetHostEntry(Dns.GetHostName());

                foreach (IPAddress ip in host.AddressList)
                {
                    if (ip.AddressFamily == AddressFamily.InterNetwork)
                    {
                        UpdatedIP.localIP = ip.ToString();
                        UpdatedIP.lastUpdate = DateTime.Now.ToShortTimeString();
                        break;
                    }
                }
            }
            else
            {
                UpdatedIP.localIP = "127.0.0.1";
                UpdatedIP.lastUpdate = DateTime.Now.ToShortTimeString();                
            }
            return UpdatedIP;
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            updatedIP = new UpdatedInfo();
            updatedIP = GetLocalIP(updatedIP);
            lblIPAddress.Text = updatedIP.localIP;
            lblInfo.Text = updatedIP.lastUpdate;             
        }
    }
}

【问题讨论】:

  • @PeterRitchie 谢谢。但我在这里没有使用任何线程概念。
  • 定时器在自己的线程上运行。所以是的,您正在使用线程...概念。
  • @Peter 对不起。我错过了。我其实忘记了。是的,你是对的。

标签: c# .net winforms


【解决方案1】:

为什么不使用 System.Windows.Forms.Timer 而不是 System.Timers.Timer? System.Windows.Forms.Timer 旨在避免此类 o 问题。

【讨论】:

  • 谢谢。它解决了我的问题。
【解决方案2】:

您需要从 Timer 线程“调用”您在 UI 上的操作。如果没有 Invoke 调用,则不允许在 Winforms UI 上进行跨线程调用。

How to invoke a UI method from another thread

【讨论】:

  • 它也有效。谢谢。
猜你喜欢
  • 2012-12-06
  • 1970-01-01
  • 2012-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多