Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否在多线程服务器上锁定资源_C#_Multithreading_Delegates_Locking_Invocation - Fatal编程技术网

C# 是否在多线程服务器上锁定资源

C# 是否在多线程服务器上锁定资源,c#,multithreading,delegates,locking,invocation,C#,Multithreading,Delegates,Locking,Invocation,我正在创建一个客户机-服务器结构,其中服务器为每个客户机都有一个线程。 该特定线程只发送和接收数据。在服务器的主线程中,我希望读取clientthread接收到的输入。但是,在主线程读取的同时,clientthread可能正在修改该输入。我该如何防止这种情况?我读过锁,但不知道如何以这种方式实现它们 我问题的第二部分是:clientthread是一个循环,它不断地从networkstream中读取数据,从而阻塞该线程,直到它能够读取某些内容为止。但是我可以从我的主线程调用现有clientthre

我正在创建一个客户机-服务器结构,其中服务器为每个客户机都有一个线程。 该特定线程只发送和接收数据。在服务器的主线程中,我希望读取clientthread接收到的输入。但是,在主线程读取的同时,clientthread可能正在修改该输入。我该如何防止这种情况?我读过锁,但不知道如何以这种方式实现它们

我问题的第二部分是:clientthread是一个循环,它不断地从networkstream中读取数据,从而阻塞该线程,直到它能够读取某些内容为止。但是我可以从我的主线程调用现有clientthread(即循环)必须执行的函数(该函数将通过该网络流发送某些内容)吗


很抱歉,我现在无法给出任何代码,但我认为已经足够清楚了?

听起来生产者-消费者设计可能非常适合您的问题。一般来说,客户机线程会将任何接收到的数据放入(线程安全)队列中,之后不会对其进行修改-到达的任何新数据都会进入队列中的新插槽。然后,主线程可以在任何队列中等待新数据,并在数据到达后进行处理。主线程可以定期检查所有队列,或者(更好)在数据放入队列时接收某种通知,这样它就可以在没有任何事情发生时休眠,并且不会占用CPU时间

既然您询问了锁:下面是一个基本的基于锁的实现,作为队列的替代方案,也许这将帮助您理解其原理

class IncomingClientData
{
    private List<byte> m_incomingData = new List<byte>();
    private readonly object m_lock = new object();

    public void Append(IEnumerable<byte> data)
    {
        lock(m_lock)
        {
            m_incomingData.AddRange(data);
        }
    }

    public List<byte> ReadAndClear()
    {
        lock(m_lock)
        {
            List<byte> result = m_incomingData;
            m_incomingData = new List<byte>();
            return result;
        }
    }
}
类IncomingClientData
{
私有列表m_incomingData=新列表();
私有只读对象m_lock=新对象();
公共void Append(IEnumerable数据)
{
锁(m_锁)
{
m_incomingData.AddRange(数据);
}
}
公共列表ReadAndClear()
{
锁(m_锁)
{
列表结果=m_输入数据;
m_incomingData=新列表();
返回结果;
}
}
}
在本例中,您的客户端线程将调用
Append
,并使用它们接收到的数据,主线程可以通过调用
ReadAndClear
来收集自上次检查以来收到的所有数据

通过在
m#lock
上锁定两个函数中的所有代码,这是线程安全的,m#lock只是一个普通的对象-您可以锁定C#中的任何对象,但我相信如果不小心使用,这可能会造成混乱,实际上会导致微妙的错误,因此我几乎总是使用专用对象来锁定。一次只有一个线程可以持有对象上的锁,因此这些函数的代码一次只能在一个线程中运行。例如,如果主线程在客户端线程仍忙于向列表中追加数据时调用
ReadAndClear
,则主线程将等待客户端线程退出
Append
函数

不需要为此创建新类,但它可以防止意外,因为我们可以小心地控制共享状态的访问方式。例如,我们知道在
ReadAndClear()
中返回内部列表是安全的,因为此时不能有对同一列表的其他引用

现在来看第二个问题:简单地调用一个方法不会导致该方法在不同的线程上运行,无论该方法在哪个类中<代码>调用是WinForms UI线程的一项特殊功能,如果您想
调用工作线程中的某个内容,则必须自己实现该功能。在内部,
Invoke
将要运行的代码放入一个队列中,队列中包含了应该在UI线程上运行的所有内容,例如UI事件。UI线程本身基本上是一个循环,它总是从该队列中提取下一项工作,然后执行该工作,然后从队列中提取下一项,依此类推。这也是为什么您不应该在事件处理程序中进行长时间工作的原因——只要UI线程忙于运行代码,它就无法处理其队列中的下一个项目,因此您将保留发生的所有其他工作项目/事件


如果你想让你的客户端线程运行某个函数,你必须提供相应的代码——例如,让客户端线程检查一些队列中是否有来自主线程的命令。

恐怕这个描述太模糊了。代码会更好。我看不出你会从中得到更多的一般性建议。事实上,这只是我需要的一般性建议:)你必须使用锁定来防止事故。这将对吞吐量非常不利,如果您有大量的客户端连接,那么所有这些线程都将争夺锁。最好的一般建议是,不这样做可以解决这个问题。我应该澄清,一个客户端的输入只能由两个线程访问:clientthread(处理IO)和主线程(使用IO更新世界)。因此clientthread只写入变量(对于每个clientthread都是唯一的),而主线程只读取该数据。还需要锁吗?我应该补充一点,这发生在一个循环中,主线程每隔50毫秒左右读取一次输入。请看“”,其中的共识是“不,他们不应该”。感谢您对我的抽象问题给出如此完整的回答!现在我知道该怎么办了,再次感谢你。但是对于第二部分,我不能用一个代表来做。例如,你可以用代表,但有趣的问题是你要用他们做什么。我已经编辑了我问题的第二部分。这可能吗?我将如何实现这一点?提前感谢,只要您在
网络流上阻塞。阅读
调用,您就不能在该线程上运行任何其他代码。然而,
网络的文档