WPF下的多线程方法重入实现不了,求指教求贴出代码谢谢!

newcomducs 2013-11-11 09:43:51
有两个控件,一个是Button,叫做bt,一个是TextBox,叫TB;程序要实现的功能是点击Button控件,TextBox上面显示1000。在程序中创建两个线程,分享同一个代码cout();Cout() 是计算1000次的功能。按照设想,点击按钮后,只会显示1000,但是现在显示出2000,程序哪里出错了?为什么实现不了多线程的方法重入了??求WPF和C#大牛解答!以下为代码。


namespace 多线程方法重入
{

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

private void bt_Click(object sender, RoutedEventArgs e)
{
ThreadStart a = new ThreadStart(Cout);
Thread thread1 = new Thread(a);
thread1.IsBackground = true;
thread1.Start();

ThreadStart b = new ThreadStart(Cout);
Thread thread2 = new Thread(b);
thread2.IsBackground = true;
thread2.Start();

}

public void Cout()
{
for (int i = 0; i < 1000;i++)
{
Dispatcher.Invoke(new Action(() =>
{
int a = int.Parse(TB.Text);
a++;
TB.Text = a.ToString();
}));
}
}
}
}
...全文
404 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
华北雪狼 2013-12-01
  • 打赏
  • 举报
回复
引用 6 楼 newcomducs 的回复:
[quote=引用 4 楼 wpfLove 的回复:]

Dispatcher.Invoke(new Action(() =>
                {
                    int a = int.Parse(TB.Text);
                    a++;
                    TB.Text = a.ToString();
                }));
你这里的代码有问题~,你只是for循环的过程是有多线程来操作,但是每个取值和赋值的过程,其实都是主线程也就是UI线程在做,所以,你其实跟没有使用多线程一样~ Dispatcher.Invoke的意思就是交给主线程来处理,所以当你主线程在处理第一个线程发起的请求时,第二个线程肯定是在阻塞的以等待主线程处理完第一个线程中的请求,再来出来第二个的
谢谢!原来是这样啊,那我要实现的功能是,我创建的两个线程共用代码Cout,而Cout方法的作用计数,从0开始1000次累加1。创建两个线程,按照线程的特点,即使线程使用同一个代码区,但是由于线程是相互独立不会影响的,所以两个线程使用Cout方法,应该都得到两个一样的结果,即两个线程都得到计算结果1000,而不是2000。麻烦看看我应该怎么做才能实现这个功能,可以的话贴上代码好吗?[/quote] 其实你两个线程虽然是调用了通一段代码,但是a的初始值是不一样的,第一次a的初始值是0,第二次第二个线程调用的时候a的初始值已经是1000了。所以你的两个线程分别循环一千次和一个线程循环两千次是一样的。 我不知道你到底想要什么样的效果,所以没法给你合理的代码。
宇峰科技 2013-11-26
  • 打赏
  • 举报
回复
namespace 多线程方法重入
{
     
    public partial class MainWindow : Window
    {
Object lockObj=new Object();
        public MainWindow()
        {
            InitializeComponent();
        }

        private void bt_Click(object sender, RoutedEventArgs e)
        {
            ThreadStart a = new ThreadStart(Cout);
            Thread thread1 = new Thread(a);
            thread1.IsBackground = true;
            thread1.Start();

            ThreadStart b = new ThreadStart(Cout);
            Thread thread2 = new Thread(b);
            thread2.IsBackground = true;
            thread2.Start();

        }

        public void Cout() 
        {
lock(lockObj)
{
            for (int i = 0; i < 1000;i++)
            {
                Dispatcher.Invoke(new Action(() =>
                {
                    int a = int.Parse(TB.Text);
                    a++;
                    TB.Text = a.ToString();
                }));
            }
}
        }
    }
}
宇峰科技 2013-11-26
  • 打赏
  • 举报
回复
两个线程调用同一段代码,要不要加锁啊。。。。
小猪八Q 2013-11-17
  • 打赏
  • 举报
回复
引用 13 楼 newcomducs 的回复:
[quote=引用 9 楼 wpfLove 的回复:] 在开始计算之前,将textBox中的值取出来,复制类一个属性和字段 然后修改你的Count方法,不要让他操作任何跟你的前台有关的东西

private string val;
        private void bt_Click(object sender, RoutedEventArgs e)
        {
            val = TB.Text;
            ThreadStart a = new ThreadStart(Cout);
            Thread thread1 = new Thread(a);
            thread1.IsBackground = true;
            thread1.Start();

            ThreadStart b = new ThreadStart(Cout);
            Thread thread2 = new Thread(b);
            thread2.IsBackground = true;
            thread2.Start();

        }

        public void Cout()
        {
            int result = 0;
            result = int.Parse(val);
            for (int i = 0; i < 1000; i++)
            {
                result++;
            }
            //在这里进行
            Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                //code进行前台的更新
                xxx.Text = result.ToString();
            }), null);
        }
我像请教一下Application.Current在此处的作用,谢谢![/quote] Application.Current代表了当前程序中的Application对象,可以理解为当前程序
宇峰科技 2013-11-15
  • 打赏
  • 举报
回复
不知道什么叫重入
newcomducs 2013-11-13
  • 打赏
  • 举报
回复
引用 9 楼 wpfLove 的回复:
在开始计算之前,将textBox中的值取出来,复制类一个属性和字段 然后修改你的Count方法,不要让他操作任何跟你的前台有关的东西

private string val;
        private void bt_Click(object sender, RoutedEventArgs e)
        {
            val = TB.Text;
            ThreadStart a = new ThreadStart(Cout);
            Thread thread1 = new Thread(a);
            thread1.IsBackground = true;
            thread1.Start();

            ThreadStart b = new ThreadStart(Cout);
            Thread thread2 = new Thread(b);
            thread2.IsBackground = true;
            thread2.Start();

        }

        public void Cout()
        {
            int result = 0;
            result = int.Parse(val);
            for (int i = 0; i < 1000; i++)
            {
                result++;
            }
            //在这里进行
            Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                //code进行前台的更新
                xxx.Text = result.ToString();
            }), null);
        }
我像请教一下Application.Current在此处的作用,谢谢!
VagGrant 2013-11-11
  • 打赏
  • 举报
回复
我不是大牛,也不懂重入、但对你的现象有些看法: 1、显示2000应该是 在线程2启动时线程一已经执行结束了吧。此时线程二的a获取到的数据时1000了。导致算出来是2000. 2、我查了下重入的概念、其中有条是重入方法中不能存在静态变量。。。而这里的tb.text相当于全局变量(或类似变量)啊 3、我的解决办法,比较蠢 private void bt_Click(object sender, RoutedEventArgs e) { int c=TB.text; ThreadStart a = new ThreadStart(Cout); Thread thread1 = new Thread(a); thread1.IsBackground = true; thread1.Start(); ThreadStart b = new ThreadStart(Cout); Thread thread2 = new Thread(b); thread2.IsBackground = true; thread2.Start(); } public void Cout() { for (int i = 0; i < 1000;i++) { Dispatcher.Invoke(new Action(() => { int a = int.Parse(c); a++; TB.Text = a.ToString(); })); }
Bonjour-你好 2013-11-11
  • 打赏
  • 举报
回复
引用 6 楼 newcomducs 的回复:
谢谢!原来是这样啊,那我要实现的功能是,我创建的两个线程共用代码Cout,而Cout方法的作用计数,从0开始1000次累加1。创建两个线程,按照线程的特点,即使线程使用同一个代码区,但是由于线程是相互独立不会影响的,所以两个线程使用Cout方法,应该都得到两个一样的结果,即两个线程都得到计算结果1000,而不是2000。麻烦看看我应该怎么做才能实现这个功能,可以的话贴上代码好吗?
为何你的 Cout() 方法会有对界面 TextBox 中的 Text 的值的引用?这就是关键!改为:
       public void Cout()
        {
            for (int i = 0; i <= 1000; i++) {
                Dispatcher.Invoke(new Action(() =>
                {
                    TB.Text = i.ToString();
                }));
            }
        }
VagGrant 2013-11-11
  • 打赏
  • 举报
回复

public void Cout()
        {
            for (int i = 1; i <= 1000; i++)
            {
                Dispatcher.Invoke(new Action(() =>
                {
                    //int a = int.Parse(TB.Text);
                    //a++;
                    TB.Text = i.ToString();
                    if (i == 1000)
                    {
                        MessageBox.Show("");
                    }
                }));
            }
        }
其实我是想知道 int a = int.Parse(TB.Text);的意思啊。为什么要有a来技术呢。这个有特别需求? if语句是debug用的。可以不要
newcomducs 2013-11-11
  • 打赏
  • 举报
回复
引用 9 楼 wpfLove 的回复:
在开始计算之前,将textBox中的值取出来,复制类一个属性和字段 然后修改你的Count方法,不要让他操作任何跟你的前台有关的东西

private string val;
        private void bt_Click(object sender, RoutedEventArgs e)
        {
            val = TB.Text;
            ThreadStart a = new ThreadStart(Cout);
            Thread thread1 = new Thread(a);
            thread1.IsBackground = true;
            thread1.Start();

            ThreadStart b = new ThreadStart(Cout);
            Thread thread2 = new Thread(b);
            thread2.IsBackground = true;
            thread2.Start();

        }

        public void Cout()
        {
            int result = 0;
            result = int.Parse(val);
            for (int i = 0; i < 1000; i++)
            {
                result++;
            }
            //在这里进行
            Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                //code进行前台的更新
                xxx.Text = result.ToString();
            }), null);
        }
谢谢,我回头试试,现在去忙,感谢你的帮忙!
小猪八Q 2013-11-11
  • 打赏
  • 举报
回复
在开始计算之前,将textBox中的值取出来,复制类一个属性和字段 然后修改你的Count方法,不要让他操作任何跟你的前台有关的东西

private string val;
        private void bt_Click(object sender, RoutedEventArgs e)
        {
            val = TB.Text;
            ThreadStart a = new ThreadStart(Cout);
            Thread thread1 = new Thread(a);
            thread1.IsBackground = true;
            thread1.Start();

            ThreadStart b = new ThreadStart(Cout);
            Thread thread2 = new Thread(b);
            thread2.IsBackground = true;
            thread2.Start();

        }

        public void Cout()
        {
            int result = 0;
            result = int.Parse(val);
            for (int i = 0; i < 1000; i++)
            {
                result++;
            }
            //在这里进行
            Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                //code进行前台的更新
                xxx.Text = result.ToString();
            }), null);
        }
newcomducs 2013-11-11
  • 打赏
  • 举报
回复
引用 4 楼 wpfLove 的回复:

Dispatcher.Invoke(new Action(() =>
                {
                    int a = int.Parse(TB.Text);
                    a++;
                    TB.Text = a.ToString();
                }));
你这里的代码有问题~,你只是for循环的过程是有多线程来操作,但是每个取值和赋值的过程,其实都是主线程也就是UI线程在做,所以,你其实跟没有使用多线程一样~ Dispatcher.Invoke的意思就是交给主线程来处理,所以当你主线程在处理第一个线程发起的请求时,第二个线程肯定是在阻塞的以等待主线程处理完第一个线程中的请求,再来出来第二个的
其实我不太了解Dispatcher.Invoke的用途,只是看到有代码使用他来解决WPF中UI线程创建的控件,不能被其他线程调用的问题,但是我的代码中需要解决方法重入,貌似这个Dispatcher.Invok解决不了。
newcomducs 2013-11-11
  • 打赏
  • 举报
回复
引用 5 楼 VagGrant 的回复:
[quote=引用 3 楼 newcomducs 的回复:] [quote=引用 1 楼 VagGrant 的回复:] 我不是大牛,也不懂重入、但对你的现象有些看法: 1、显示2000应该是 在线程2启动时线程一已经执行结束了吧。此时线程二的a获取到的数据时1000了。导致算出来是2000. 2、我查了下重入的概念、其中有条是重入方法中不能存在静态变量。。。而这里的tb.text相当于全局变量(或类似变量)啊 3、我的解决办法,比较蠢 private void bt_Click(object sender, RoutedEventArgs e) { int c=TB.text; ThreadStart a = new ThreadStart(Cout); Thread thread1 = new Thread(a); thread1.IsBackground = true; thread1.Start(); ThreadStart b = new ThreadStart(Cout); Thread thread2 = new Thread(b); thread2.IsBackground = true; thread2.Start(); } public void Cout() { for (int i = 0; i < 1000;i++) { Dispatcher.Invoke(new Action(() => { int a = int.Parse(c); a++; TB.Text = a.ToString(); })); }
谢谢,但是这个代码我在VS上试运行了,有错误;首先控件TXB的Text属性中内容是字符型的, int c=TXB.text不能直接赋值,其次在方法Cout中的 int a = int.Parse(c);实际上起不到累加计数的作用。很感谢你的回答,希望能帮忙继续看看![/quote] 额。第一个是我手快写错了。应该是int c=int.Parse(TB.Text); 然后,跟楼上说的一样代码有问题啊。你写的代码 Dispatcher.Invoke(new Action(() => { int a = int.Parse(TB.Text); a++; TB.Text = a.ToString(); })); a就是一个累加器的作用啊。每for一次,TB.Text就加一。加个断点看看呢。或者说说你想实现的功能。以便我们对你的代码进一步理解或者找其他实现方式[/quote] 我要实现的功能是,我创建的两个线程共用代码Cout,而Cout方法的作用计数,从0开始1000次累加1。创建两个线程,按照线程的特点,即使线程使用同一个代码区,但是由于线程是相互独立不会影响的,所以两个线程使用Cout方法,应该都得到两个一样的结果,即两个线程都得到计算结果1000,而不是2000。麻烦看看我应该怎么做才能实现这个功能,可以的话贴上代码好吗?
newcomducs 2013-11-11
  • 打赏
  • 举报
回复
引用 4 楼 wpfLove 的回复:

Dispatcher.Invoke(new Action(() =>
                {
                    int a = int.Parse(TB.Text);
                    a++;
                    TB.Text = a.ToString();
                }));
你这里的代码有问题~,你只是for循环的过程是有多线程来操作,但是每个取值和赋值的过程,其实都是主线程也就是UI线程在做,所以,你其实跟没有使用多线程一样~ Dispatcher.Invoke的意思就是交给主线程来处理,所以当你主线程在处理第一个线程发起的请求时,第二个线程肯定是在阻塞的以等待主线程处理完第一个线程中的请求,再来出来第二个的
谢谢!原来是这样啊,那我要实现的功能是,我创建的两个线程共用代码Cout,而Cout方法的作用计数,从0开始1000次累加1。创建两个线程,按照线程的特点,即使线程使用同一个代码区,但是由于线程是相互独立不会影响的,所以两个线程使用Cout方法,应该都得到两个一样的结果,即两个线程都得到计算结果1000,而不是2000。麻烦看看我应该怎么做才能实现这个功能,可以的话贴上代码好吗?
VagGrant 2013-11-11
  • 打赏
  • 举报
回复
引用 3 楼 newcomducs 的回复:
[quote=引用 1 楼 VagGrant 的回复:] 我不是大牛,也不懂重入、但对你的现象有些看法: 1、显示2000应该是 在线程2启动时线程一已经执行结束了吧。此时线程二的a获取到的数据时1000了。导致算出来是2000. 2、我查了下重入的概念、其中有条是重入方法中不能存在静态变量。。。而这里的tb.text相当于全局变量(或类似变量)啊 3、我的解决办法,比较蠢 private void bt_Click(object sender, RoutedEventArgs e) { int c=TB.text; ThreadStart a = new ThreadStart(Cout); Thread thread1 = new Thread(a); thread1.IsBackground = true; thread1.Start(); ThreadStart b = new ThreadStart(Cout); Thread thread2 = new Thread(b); thread2.IsBackground = true; thread2.Start(); } public void Cout() { for (int i = 0; i < 1000;i++) { Dispatcher.Invoke(new Action(() => { int a = int.Parse(c); a++; TB.Text = a.ToString(); })); }
谢谢,但是这个代码我在VS上试运行了,有错误;首先控件TXB的Text属性中内容是字符型的, int c=TXB.text不能直接赋值,其次在方法Cout中的 int a = int.Parse(c);实际上起不到累加计数的作用。很感谢你的回答,希望能帮忙继续看看![/quote] 额。第一个是我手快写错了。应该是int c=int.Parse(TB.Text); 然后,跟楼上说的一样代码有问题啊。你写的代码 Dispatcher.Invoke(new Action(() => { int a = int.Parse(TB.Text); a++; TB.Text = a.ToString(); })); a就是一个累加器的作用啊。每for一次,TB.Text就加一。加个断点看看呢。或者说说你想实现的功能。以便我们对你的代码进一步理解或者找其他实现方式
小猪八Q 2013-11-11
  • 打赏
  • 举报
回复

Dispatcher.Invoke(new Action(() =>
                {
                    int a = int.Parse(TB.Text);
                    a++;
                    TB.Text = a.ToString();
                }));
你这里的代码有问题~,你只是for循环的过程是有多线程来操作,但是每个取值和赋值的过程,其实都是主线程也就是UI线程在做,所以,你其实跟没有使用多线程一样~ Dispatcher.Invoke的意思就是交给主线程来处理,所以当你主线程在处理第一个线程发起的请求时,第二个线程肯定是在阻塞的以等待主线程处理完第一个线程中的请求,再来出来第二个的
newcomducs 2013-11-11
  • 打赏
  • 举报
回复
引用 1 楼 VagGrant 的回复:
我不是大牛,也不懂重入、但对你的现象有些看法: 1、显示2000应该是 在线程2启动时线程一已经执行结束了吧。此时线程二的a获取到的数据时1000了。导致算出来是2000. 2、我查了下重入的概念、其中有条是重入方法中不能存在静态变量。。。而这里的tb.text相当于全局变量(或类似变量)啊 3、我的解决办法,比较蠢 private void bt_Click(object sender, RoutedEventArgs e) { int c=TB.text; ThreadStart a = new ThreadStart(Cout); Thread thread1 = new Thread(a); thread1.IsBackground = true; thread1.Start(); ThreadStart b = new ThreadStart(Cout); Thread thread2 = new Thread(b); thread2.IsBackground = true; thread2.Start(); } public void Cout() { for (int i = 0; i < 1000;i++) { Dispatcher.Invoke(new Action(() => { int a = int.Parse(c); a++; TB.Text = a.ToString(); })); }
谢谢,但是这个代码我在VS上试运行了,有错误;首先控件TXB的Text属性中内容是字符型的, int c=TXB.text不能直接赋值,其次在方法Cout中的 int a = int.Parse(c);实际上起不到累加计数的作用。很感谢你的回答,希望能帮忙继续看看!
newcomducs 2013-11-11
  • 打赏
  • 举报
回复
谢谢,但是这个代码我在VS上试运行了,有错误;首先控件TXB的Text属性中内容是字符型的, int c=TXB.text不能直接赋值,其次在方法Cout中的 int a = int.Parse(c);实际上起不到累加计数的作用。很感谢你的回答,希望能帮忙继续看看!

8,756

社区成员

发帖
与我相关
我的任务
社区描述
WPF/Silverlight相关讨论
社区管理员
  • WPF/Silverlight社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧