C# 一个线程中影响另一个线程路径的值

C# 一个线程中影响另一个线程路径的值,c#,multithreading,server,C#,Multithreading,Server,我有一个程序,它使用两个客户端线程和一个服务器。在我的程序中有一个点,我希望一个线程中的值影响另一个线程的路径 更具体地说,我在服务器中有以下代码: class Handler { public void clientInteraction(Socket connection, bool isFirstThread, Barrier barrier) { string pAnswer = string.Empty; string endGame

我有一个程序,它使用两个客户端线程和一个服务器。在我的程序中有一个点,我希望一个线程中的值影响另一个线程的路径

更具体地说,我在服务器中有以下代码:

class Handler 
{
    public void clientInteraction(Socket connection, bool isFirstThread, Barrier barrier)

    {
        string pAnswer = string.Empty;
        string endGameTrigger = string.Empty;
        //setup streamReaders and streamWriters

        while(true) //infinite game loop
        {
            //read in a question and send to both threads.
            pAnswer = sr.ReadLine();
            Console.WriteLine(pAnswer);

            awardPoints(); 

            writeToConsole("Press ENTER to ask another question or enter 0 to end the game", isFirstThread);
            if(isFirstThread == true)
            {
                endGameTrigger = Console.ReadLine(); //this is only assigning to one thread...
            }

            barrier.SignalAndWait();

            if(endGameTrigger == "0")//...meaning this is never satisfied in one thread
            {
                endGame();
            }           

        }
    }
}   
布尔值
isFirstThread
是在线程的构造函数中设置的一个值,我可以检测哪个线程首先连接到该线程


是否有某种方式或线程方法允许第二个连接的线程检测到第一个线程中的
endGameTrigger
已设置,因此两个线程都正确执行
endGame()
方法

回应鲁安的评论。我将
endGameTrigger
作为
private静态字符串endGameTrigger
放在处理程序类中。使其成为
静态
字段而不是本地方法变量,允许
处理程序
类的所有实例(每个线程)访问此变量的最新赋值。非常感谢。

最好关注多线程

  • 如果出于性能/UI原因,绝对有必要启动单独的线程
  • 如果您的代码可能在多线程环境(如网站)中运行,并且您需要知道当多个线程对同一类或同一值进行操作时,代码不会中断
但要格外小心。多线程的不正确使用/处理可能会导致代码的行为不可预测且不一致。有些东西在大部分时间都会起作用,然后又无缘无故地不起作用。bug将很难复制和识别

也就是说,处理多线程的一个基本概念是确保两个线程不会试图同时更新相同的值。它们可以损坏或部分修改值,这对于单个线程来说是不可能的

实现这一点的一种方法是使用

您通常有一个只作为锁存在的对象。当一个线程进入该
lock
块时,它将获得对象上的锁。如果另一个线程已经在该对象上拥有锁,那么下一个线程只会等待前一个线程释放锁。这确保了两个线程不能同时更新该值

您希望使
锁中的代码量尽可能小,以便尽快释放锁。请注意,如果多个锁变得复杂,那么两个线程可能会永久性地相互阻塞

对于递增和更新数字,还有一些方法可以为您处理锁定,确保这些操作一次由一个线程执行

只是为了好玩,我写了这个控制台应用程序。它接受一个句子,将其拆分为单词,然后使用多个线程将每个单词添加回一个新字符串,并输出该字符串

using System;
using System.Threading.Tasks;

namespace FunWithThreading
{
    class Program
    {
        static void Main(string[] args)
        {
            var sentence =
                "I am going to add each of these words to a string "
                + "using multiple threads just to see what happens.";
            var words = sentence.Split(' ');
            var output = "";
            Parallel.ForEach(words, word => output = output + " " + word);
            Console.WriteLine(output);
            Console.ReadLine();
        }
    }
}
前两次运行时,输出字符串正是我开始使用的字符串。太好了,它工作得很好!然后我得到了这个:

我将使用多个线程将这些单词添加到字符串中,看看会发生什么。每个

然后我又运行了20次,无法重复错误。试想一下,如果这是一个真正的应用程序,并且发生了一些不可预知的事情,即使我反复测试,然后我无法让它再次发生,会有多么沮丧


因此,重点不是多线程是邪恶的,而是为了理解风险,只需要在需要时介绍它,然后仔细考虑如何防止线程相互干扰。您还需要添加同步。请参阅我的评论-您不希望多个线程修改同一字符串(或其他值),除非您使用锁来确保它们不会试图在同一时间修改它。奇怪的、不可预测的、不一致的事情可能会发生,也将发生。我的代码在任何时候都只处理两个线程,并且只有第一个线程(由布尔值标识)在更改值时进行操作。另一个线程将只访问变量以查找值,而不会设置新值。因此,在这种情况下,我的答案是一个补丁。尽管如此!您在锁定方面的输入当然很有趣,而且无可比拟地比编码实践要好得多,尽管我可能不需要这样做,但我现在正在研究锁定。非常感谢您提醒我这个问题。一个线程读取而另一个线程写入并不重要。一个在读,另一个在写。修复程序在大多数情况下都会起作用,但之后就不行了。有些事情发生在幕后,我们不知道也不去想,只要我们的操作是单线程的,它们就不会影响我们。这就是为什么即使应用程序是多线程的,我们也需要确保代码的某些部分,比如读写单个字符串,是单线程的。
using System;
using System.Threading.Tasks;

namespace FunWithThreading
{
    class Program
    {
        static void Main(string[] args)
        {
            var sentence =
                "I am going to add each of these words to a string "
                + "using multiple threads just to see what happens.";
            var words = sentence.Split(' ');
            var output = "";
            Parallel.ForEach(words, word => output = output + " " + word);
            Console.WriteLine(output);
            Console.ReadLine();
        }
    }
}