线程间操作无效: 从不是创建控件“textBox1”的线程访问它(未处理System.InvalidOperationException)(委托)delegate,Invoke,BeginInvoke

本文主要是介绍线程间操作无效: 从不是创建控件“textBox1”的线程访问它(未处理System.InvalidOperationException)(委托)delegate,Invoke,BeginInvoke,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

目录

1.问题复现

2.分析问题

3.解决办法

4.写法拓展

5.总结与源码

//长话短说 //本文将逐步的的引导并解决此问题//大家互相交流,有不足处请指正

//源码在本文最后面

 

  1. 问题复现

新建WinForm程序 ,界面 Form1,拖个 button1 和textBox1,然后Button1中增加click事件,其中Form1.cs中部分代码如下:

private void button1_Click(object sender, EventArgs e)

{

    System.Threading.Thread Thread_1 = new System.Threading.Thread(ThreadOne);

    Thread_1.IsBackground = true//设置为后台线程,软件关闭则线程关闭

    Thread_1.Start();  //线程中若想传值可此处将值传过去,比如我想传个字符串的值,此处可 Thread_1.Start("传值")

}

private void ThreadOne() //线程中若想传值可设置为object类型,即 ThreadOne(object obj)

{

    MessageBox.Show("即将运行报错的代码!");

    textBox1.Text = " 在这个线程里改变控件的值"; //会报异常   Message=线程间操作无效: 从不是创建控件“textBox1”的线程访问它。

}

编译运行后如下图,复现此BUG:

文字提示如下:

未处理System.InvalidOperationException

  Message=线程间操作无效: 从不是创建控件“textBox1”的线程访问它。

  Source=System.Windows.Forms

  StackTrace:

       在 System.Windows.Forms.Control.get_Handle()

       在 System.Windows.Forms.Control.set_WindowText(String value)

       在 System.Windows.Forms.TextBoxBase.set_WindowText(String value)

2.分析问题

仔细看错误提示为: 线程间操作无效: 从不是创建控件“textBox1”的线程访问它。

这句话字面意思是这个控件只能被创建它的线程访问,即线程A中创建了控件A1,若线程B中想修改控件A1的属性,则不允许!(如下图)

3.解决办法

那么能否找个中间变量或者在A线程中有某种方法可以让线程B中执行的某段代码可以从线程B中跳到线程A中,然后线程A改控件A1中的信息 ,这样就是A改A中创建的控件A1了,如下图

那么这个中间变量是什么呢?此时就用到了关键字 delegate(委托),

然后我们试试 通过用这个关键字可以解决我们遇到的问题吗?同时我们也得确认下他提示的”不是从创建的线程中访问它”这句话是否正确,既然是线程,那么我们就在System.Threading.Thread下面搜,然后就我们搜到了如下信息:

可获得当前唯一标识符(ID)的代码:

int NowThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;

可获得当前工作的线程的名字(Name)的代码:

 string NowThreadName = System.Threading.Thread.CurrentThread.Name;

仔细看描述,发现唯一标识符(ID)只读,不可设,而当前工作的线程的名字(Name)可以设置的,那我们就选择Name来判断当前工作的线程是哪个。然后我们新建个WinForm程序,然后在第一个桌面程序Form1的构造函数中提前设置主线程Name为MainThread

代码如下

public Form1()

{

   InitializeComponent();

   System.Threading.Thread.CurrentThread.Name = "MainThread"; //备注:软件开启后只能设置一次

}

然后设计器中拖个button2新增个click事件,

提前设置好子线程的Name为:ThreadTwo声明一个叫SetText_delegate的委托,但是目前这个委托不知道怎么调用啊,既然不知道,那先按普通的方法那样调用,

相关代码如下

private void button2_Click(object sender, EventArgs e)

{

    MessageBox.Show("当前线程Name:" + System.Threading.Thread.CurrentThread.Name);

    System.Threading.Thread Thread_2 = new System.Threading.Thread(ThreadTwo);

    Thread_2.Name = "ThreadTwo";   //设置子线程Name

Thread_2.IsBackground = true//设置为后台线程,软件关闭则线程关闭

    Thread_2.Start();

}

private delegate void SetText_delegate(string sssext); //声明一个委托  //相当于在此线程中定义一个方法p

rivate void SetText(string str)

{

    MessageBox.Show("哈哈,跳到这里来了,当前线程Name:" + System.Threading.Thread.CurrentThread.Name);

    textBox1.Text = str + ",赋值部分!";

}

private void ThreadTwo()

{

    MessageBox.Show("正常定义委托,即将更改值!!" + "当前线程Name:" + System.Threading.Thread.CurrentThread.Name);

    SetText_delegate aInThread = new SetText_delegate(SetText);  //核心代码

aInThread("线程中直接传递参数,报错"); //报错:此处直接调用则当前工作线程还是子线程

}

以上代码运行过后发现在aInThread("线程中直接传递参数,报错"); 处还是会报同样的错误

提取部分报错内容如下:

Message=线程间操作无效: 从不是创建控件“textBox1”的线程访问它。

在 WindowsFormsApplication1.Form1.SetText(String str) 位置 d:\Projects\C#\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行号 91

在 WindowsFormsApplication1.Form1.ThreadTwo() 位置 d:\Projects\C#\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行号 100

上面报错验证了子线程中委托方法实例化后直接调用主线程中的方法是不可行的,仔细查看发现控件textBox1赋值前的MessageBox.Show中提示当前工作线程还是: ThreadTwo

直接调用走不通,那么是否是委托不行或者是我们不会用这个委托?

这时我们查到了关键字Invoke/BeginInvoke那么这个关键字的作用是什么?怎么用?

按F12或则在Invoke处右键选择转到定义,然后我们发现了下图信息,

关键字:

英文截图如下:

OK,这里写出了 这个Invoke使用的前提如下

  1. 在拥有控件的基础窗口句柄的线程上,(Executes the specified delegate,
  2. 用指定的参数列表执行指定委托(on the thread that owns the control's underlying window handle
  3. Invoke运行需要两个参数,一个是Delegate类型的,另一个是Object类型,即普通参数

可是我们如何用如何用Invoke呢,突然想到线程ThreadTwo也是处于MainThread中(即线程的Name,前文有写),

然后我们将线程中ThreadTwo方法内的aInThread方法注释掉,然后可改为如下:

private void ThreadTwo()

{

   MessageBox.Show("正常定义委托,即将更改值!!" + "当前线程Name:" + System.Threading.Thread.CurrentThread.Name);

   SetText_delegate aInThread = new SetText_delegate(SetText);  //核心代码

   MessageBox.Show("正常定义委托,即将更改值!!当前线程Name:" + System.Threading.Thread.CurrentThread.Name); ;

  //aInThread("线程中直接传递参数,报错"); //报错:此处直接调用则当前工作线程还是子线程

   this.Invoke(aInThread, "第一种写法,我要赋值了呦!");  //核心代码

   MessageBox.Show("正常定义委托,当前线程Name:" + System.Threading.Thread.CurrentThread.Name);

}

然后编译运行,成功赋值!成功将值赋给了textBox1

那么下图应改为如下:

准确来说应该如下图

通过以上我们知道了Invoke和委托二者缺一不可,只有运行到Invoke才会触发方法SetText给控件textBox1赋值,那么软件运行的顺序是什么呢?每运行一步我都加个MessageBox来查看软件的运行顺序,实际弹窗的顺序如下:

从上图中标记处,我们就很容易得出委托实例化时没有运行到方法内部,只有运行到Invoke时才会运行到方法SetText,进而改变textBox1属性,

或者看着麻烦也可以改成这样儿

即线程ThreadTwo中调用方法Test,方法Test仍然在子线程ThreadTwo中,而只有Invoke调用的委托函数SetTest在MainThread中,

 

那么现在我们定义了两个方法,方法SetText和方法Test,两个方法可否合二为一?

我们可以试着判断,若是仍然在线程ThreadTwo中则继续运行目前方法Test中的内容,若当前运行的线程为MainThread就对textBox1进行赋值,

主线程赋值代码:System.Threading.Thread.CurrentThread.Name = "MainThread"; //备注:软件开启后只能设置一次

那么方法可改为  

private void button2_Click(object sender, EventArgs e)

{

    MessageBox.Show("当前线程Name:" + System.Threading.Thread.CurrentThread.Name, "1");

    System.Threading.Thread Thread_2 = new System.Threading.Thread(ThreadTwo);

    Thread_2.Name = "ThreadTwo";   //设置子线程Name

    Thread_2.IsBackground = true//设置为后台线程,软件关闭则线程关闭

    Thread_2.Start();

}

private void ThreadTwo()

{

    NewTest("我要赋值了呦!");

}

private delegate void SetText_delegate(string sssext); //声明一个委托  //相当于在此线程中定义一个方法

private void NewTest(string str)

{

    if (!System.Threading.Thread.CurrentThread.Name.Equals("MainThread"))

    {

        SetText_delegate aInThread = new SetText_delegate(SetText);  //核心代码

        this.Invoke(aInThread, str + ",调用Invoke调用");  //核心代码

    }

    else

    {

        textBox1.Text = str + ",赋值了!";

    }

}

然后运行结果如下

那么如果我不会设置主线程的Name呢?

有方法:麻烦将

if (!System.Threading.Thread.CurrentThread.Name.Equals("MainThread"))

替换成

if (this.InvokeRequired)

试试看,哇塞,居然也可以,而且貌似替换后就变成了网上主流的方式。

4.多种写法

4.1网络正常写法及变种

网上主流的方式基本上是如下:

private void button2_Click(object sender, EventArgs e)

{

    System.Threading.Thread Thread_2 = new System.Threading.Thread(ThreadTwo);

    Thread_2.IsBackground = true//设置为后台线程,软件关闭则线程关闭

    Thread_2.Start();

}

private delegate void SetText_delegate(string sssext); //声明一个委托  //相当于在此线程中定义一个方法

private void ThreadTwo()

{

    NewTest("我要赋值了呦!");

}

private void NewTest(string str)

{

    //if (!System.Threading.Thread.CurrentThread.Name.Equals("MainThread"))

    if (this.InvokeRequired)

    {

        SetText_delegate aInThread = new SetText_delegate(SetText);  //核心代码

        this.Invoke(aInThread, str + ",调用Invoke调用");  //核心代码

    }

    else

    {

        textBox1.Text = str + ",赋值了!";

    }

}

那么有没有些变种写法呢?

有在Invoke/BeginInvoke处按F12或则在Invoke处右键选择转到定义,然后我们发现了下图信息,

    //public object Invoke(Delegate method);

    //public object Invoke(Delegate method, params object[] args);

    //public IAsyncResult BeginInvoke(Delegate method);

    //public IAsyncResult BeginInvoke(Delegate method, params object[] args);

意思就是无论什么方法,只要第一个参数是Delegate就行,

如果我们把网上的方法当作第0种写法,我前面写的当作第一种写法,其他的依次往后排:

private void ThreadTwo()

{

    //第0种写法

    NewTest("我要赋值了呦!");

 

    第一种写法

    SetText_delegate aInThread = new SetText_delegate(SetText_NoReturn);  //核心代码

    this.Invoke(aInThread, "第一种写法,我要赋值了呦!");  //核心代码

 

    //第二种写法

    SetText_delegate SetText_d = SetText_NoReturn;

    this.Invoke(SetText_d, new object[] { "第二种写法,我还要赋值了呦!" }); //变种方式如上

 

    //第三种写法

    this.Invoke(new SetText_delegate(SetText_NoReturn), "第三种写法,我又要赋值了呦!"); //变种方式如上

 

    //第四种写法        

    this.Invoke((SetText_delegate)SetText_NoReturn, "第四种写法,我再次要赋值了呦!"); //变种方式如上

 

    //第五种写法

    Action<string> ffaff = new Action<string>(SetText_NoReturn);

    this.Invoke(ffaff, "5555555555");

 

    //第六种写法

    Action<string> fffaff = SetText_NoReturn;

    this.Invoke(fffaff, "666666666666");

 

    //第七种写法

    this.Invoke(new Action<string>(SetText), "7777777777");

 

    //第八种写法   //Func是.NET里面的内置委托,它有很多重载。//第一个值是参数,第二个值是返回值

    Func<string, string> ssfada = new Func<string, string>(SetText_ReturnStr);

    this.Invoke(ssfada, "8888888888");

 

    //第九种写法

    Func<string, string> ssfaa = SetText_ReturnStr;

    this.Invoke(ssfaa, "999999999999");

 

    //第十种写法

    this.Invoke(new Func<string, string>(SetText_ReturnStr), "无论何种写法,Invoke第一个参数必须为Delegate类型");

 

    //以上this.textBox1.Invoke 可改为 this.textBox1.BeginInvoke 或者 this.Invoke 或者 this.BeginInvoke 功能相同

}

private delegate void SetText_delegate(string sssext); //声明一个委托  //相当于在此线程中定义一个方法

private void SetText_NoReturn(string str)

{

    textBox1.Text = str;

    MessageBox.Show(str);

}

private string SetText_ReturnStr(string str)

{

    textBox1.Text = str;

    MessageBox.Show(str);

    return str; //随便返回个字符串就行

}

那么有没有直接在线程里面直接可以操作的?

4.2 BeginInvoke的作用

相关代码如下,其中SetText_delegate本文前面定义过

private void button3_Click(object sender, EventArgs e)

{

    MessageBox.Show("当前线程Name:" + System.Threading.Thread.CurrentThread.Name, "1");

    System.Threading.Thread Thread_3 = new System.Threading.Thread(ThreadThree);

    Thread_3.Name = "ThreadThree";

    Thread_3.IsBackground = true;

    Thread_3.Start();

}

private void ThreadThree()

{                  //System.Threading.Thread.CurrentThread.Name 值为 ThreadThree

    MessageBox.Show("进入线程中,当前线程Name:" + System.Threading.Thread.CurrentThread.Name, "2");

    string strargs = "我要赋 值了呦! " + button3.Text;

    SetText_delegate setText = delegate(string str)

    {                                                        //MainThread  //这就说明delegate只是起到了函数指针的作用

        MessageBox.Show("即将改值,当前线程Name:" + System.Threading.Thread.CurrentThread.Name, "4");

        this.textBox1.Text = str;

    };

    MessageBox.Show("线程运行中,线程:" + System.Threading.Thread.CurrentThread.Name, "3");

    this.BeginInvoke(setText, new object[] { "赋值" });

    MessageBox.Show("线程运行中,线程:" + System.Threading.Thread.CurrentThread.Name, "5");

}

 

BeginInvoke运行结果如下:

 

4.3 超简写

那么有没有可以用最小行数的代码来实现此功能呢?

答:有,代码如下(本文最后有源码下载链接)

#region 委托(超简写)

private delegate void delegate_ParameterOne(string s);  //带一个参数的

private delegate void delegate_ParameterNo();         //不带参数的

private void button4_Click(object sender, EventArgs e)

{

    System.Threading.Thread Thread_4 = new System.Threading.Thread(ThreadFour);

    Thread_4.Name = "ThreadFour";

    Thread_4.IsBackground = true;

    Thread_4.Start();

}

private void ThreadFour()

{

    //我们都知道Invoke有两种用法,那么什么时候用一个参数,什么时候用两个参数呢?            //请往下看

    //public object Invoke(Delegate method);

    //public object Invoke(Delegate method, params object[] args);

    MessageBox.Show("即将开始改变textBox1的值");

    int n = 0; string strMessage = "";

    //以下方法中,通过Invoke的第二个参数来传值    strMessage 等同于  new object[] { strMessage }

    n = 1; strMessage = string.Format("这是第 {0} 种写法", n);

    delegate_ParameterOne setText = delegate(string str) { this.textBox1.Text = str; };

    this.Invoke(setText, strMessage);

    MessageBox.Show(strMessage);

 

    n = 2; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke((delegate_ParameterOne)(delegate(string str) { this.textBox1.Text = str; }), strMessage);

    MessageBox.Show(strMessage);

 

    n = 3; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke((delegate_ParameterOne)((string str) => { this.textBox1.Text = str; }), strMessage);

    MessageBox.Show(strMessage);

 

    n = 4; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke(new delegate_ParameterOne(delegate(string str) { this.textBox1.Text = str; }), strMessage);

    MessageBox.Show(strMessage);

 

    n = 5; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke(new delegate_ParameterOne((string str) => { this.textBox1.Text = str; }), strMessage);

    MessageBox.Show(strMessage);

 

    //以下是不带参数而传值的写法

    n = 6; strMessage = string.Format("这是第 {0} 种写法", n);

    delegate_ParameterNo setT = delegate() { this.textBox1.Text = strMessage; };

    this.Invoke(setT);

    MessageBox.Show(strMessage);

 

    n = 7; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke((delegate_ParameterNo)(delegate() { this.textBox1.Text = strMessage; }));

    MessageBox.Show(strMessage);

 

    n = 8; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke((delegate_ParameterNo)(() => { this.textBox1.Text = strMessage; }));

    MessageBox.Show(strMessage);

 

    n = 9; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke(new delegate_ParameterNo(delegate() { this.textBox1.Text = strMessage; }));

    MessageBox.Show(strMessage);

 

    n = 10; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke(new delegate_ParameterNo(() => { this.textBox1.Text = strMessage; }));

    MessageBox.Show(strMessage);

 

    n = 11; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke(new delegate_ParameterOne((string str) => { this.textBox1.Text = strMessage; }), new object[] { null });

    //注意:第二个参数直接接写null会报错

    MessageBox.Show(strMessage);

 

    //通过以上十一个方法我们总结出了如何用哪种Invoke中取决于 定义delegate类型的方法时候带不带参数

    //如不带,即像定义delegate_ParameterNo时需要用一个参数的Invoke,即

    //public object Invoke(Delegate method);

    //如带参数,即像定义delegate_ParameterOne时需要用两个个参数的Invoke,即

    //public object Invoke(Delegate method, params object[] args);

 

    n = 12; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke((Func<string, string>)delegate(string str) { textBox1.Text = str; return ""; }, strMessage);

    MessageBox.Show(strMessage);  //Func中第二个参数为返回值类,可改

 

    n = 13; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke((Func<string, string>)delegate { textBox1.Text = strMessage + "," + strMessage; return ""; }, "此变量无作用");

    MessageBox.Show(strMessage);  //Func中第二个参数为返回值类,可改

 

    n = 14; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke((Func<string, string>)delegate { textBox1.Text = strMessage; return ""; }, "");

    MessageBox.Show(strMessage);

 

    n = 15; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke(new Func<string>(() => { textBox1.Text = strMessage; return ""; }));

    MessageBox.Show(strMessage);

 

    n = 16; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke(new MethodInvoker(delegate() { textBox1.Text = strMessage; }));

    MessageBox.Show(strMessage);

 

    n = 17; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke(new Action(delegate { textBox1.Text = strMessage; }));

    MessageBox.Show(strMessage);

 

    n = 18; strMessage = string.Format("这是第 {0} 种写法", n);//lambda表达式

    this.Invoke(new Action(() => { textBox1.Text = strMessage; }));

    MessageBox.Show(strMessage);

 

    n = 19; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke(new EventHandler(delegate { textBox1.Text = strMessage; }));

    MessageBox.Show(strMessage);

 

    n = 20; strMessage = string.Format("这是第 {0} 种写法", n);

    this.Invoke((EventHandler)delegate { textBox1.Text = strMessage; });

    MessageBox.Show(strMessage);

 

    MessageBox.Show("总结,写法再多也是为了实现功能,记不住就记网上最经典的方法好了,一法通万法通!", "总结");

}

#endregion

 

5.总结与源码

5.1总结

对于本文题目的问题,个人认为我们应该主要了解及怎么使用Invoke/BeginVoke,其次才是delegate的使用。

总结本博文前半部分主要写了delegate的用法,及如何使用Invoke,什么情况下使用Invoke,怎么使用Invoke。

本文中间写了InvokeRequired的作用,

后半部分写了Beginvoke的作用,捎带提了Action的用法,Func的用法,EventHandler的用法。

其实还是有种方法关闭线程安全检查,即

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; //关闭安全检查

极其不建议如此做,原因关闭安全检查是就相当于 消防检查出问题了,但是你每次都忽略。

5.2源码:

源代码为Visual Studio 2012环境下编译的

源代码链接:

https://download.csdn.net/download/shengmingzaiyuxuexi/12274875(推荐)

https://download.csdn.net/download/shengmingzaiyuxuexi/12264023(前一版本,仅供借鉴)

若没积分,请留言或私信。

 

 

本文参考链接:https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2008/ms171728(v=vs.90)?redirectedfrom=MSDN

 

 

有错误,请指正

有疑问,请留言

与君共勉,共同进步!

这篇关于线程间操作无效: 从不是创建控件“textBox1”的线程访问它(未处理System.InvalidOperationException)(委托)delegate,Invoke,BeginInvoke的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/433673

相关文章

Python ZIP文件操作技巧详解

《PythonZIP文件操作技巧详解》在数据处理和系统开发中,ZIP文件操作是开发者必须掌握的核心技能,Python标准库提供的zipfile模块以简洁的API和跨平台特性,成为处理ZIP文件的首选... 目录一、ZIP文件操作基础三板斧1.1 创建压缩包1.2 解压操作1.3 文件遍历与信息获取二、进阶技

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-

Java中字符串转时间与时间转字符串的操作详解

《Java中字符串转时间与时间转字符串的操作详解》Java的java.time包提供了强大的日期和时间处理功能,通过DateTimeFormatter可以轻松地在日期时间对象和字符串之间进行转换,下面... 目录一、字符串转时间(一)使用预定义格式(二)自定义格式二、时间转字符串(一)使用预定义格式(二)自

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

JAVA保证HashMap线程安全的几种方式

《JAVA保证HashMap线程安全的几种方式》HashMap是线程不安全的,这意味着如果多个线程并发地访问和修改同一个HashMap实例,可能会导致数据不一致和其他线程安全问题,本文主要介绍了JAV... 目录1. 使用 Collections.synchronizedMap2. 使用 Concurren

Java Response返回值的最佳处理方案

《JavaResponse返回值的最佳处理方案》在开发Web应用程序时,我们经常需要通过HTTP请求从服务器获取响应数据,这些数据可以是JSON、XML、甚至是文件,本篇文章将详细解析Java中处理... 目录摘要概述核心问题:关键技术点:源码解析示例 1:使用HttpURLConnection获取Resp

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

Python处理函数调用超时的四种方法

《Python处理函数调用超时的四种方法》在实际开发过程中,我们可能会遇到一些场景,需要对函数的执行时间进行限制,例如,当一个函数执行时间过长时,可能会导致程序卡顿、资源占用过高,因此,在某些情况下,... 目录前言func-timeout1. 安装 func-timeout2. 基本用法自定义进程subp