C# 如何锁定成员变量?
出于示例目的,我简化了此代码:C# 如何锁定成员变量?,c#,multithreading,locking,C#,Multithreading,Locking,出于示例目的,我简化了此代码: class TextLogger : IDisposable { private FileStream m_FileStream; private StreamWriter m_StreamWriter; void CreateNewLogFile() { //Open the File m_FileStream = File.Open( m_CurrentFileName,
class TextLogger : IDisposable
{
private FileStream m_FileStream;
private StreamWriter m_StreamWriter;
void CreateNewLogFile()
{
//Open the File
m_FileStream = File.Open(
m_CurrentFileName,
FileMode.OpenOrCreate,
FileAccess.Write,
FileShare.Read );
m_StreamWriter = new StreamWriter( m_FileStream );
....
}
}
在尝试新建StreamWriter时,我得到一个
InvalidArgumentException
,因为m_FileStream
已经被另一个线程处理,并且为null(m_StreamWriter
也为null)。如何在成员变量周围设置锁?您应该这样做
class TextLogger : IDisposable
{
private FileStream m_FileStream;
private StreamWriter m_StreamWriter;
private object m_Lock = new object();
void CreateNewLogFile()
{
lock (m_Lock)
{
if ( m_FileStream != null )
m_StreamWriter = new StreamWriter(m_FileStream);
};
}
void CalledFromOtherThread()
{
//Do stuff
lock (m_Lock)
{
if (m_FileStream != null)
m_FileStream.Dispose();
m_FileStream = null;
}
}
}
当从其他线程调用
时,它应该获取锁,然后处理m_文件流。这样,在CreateNewLogFile
中,您将永远不会有一个已处理的文件流您应该这样做
class TextLogger : IDisposable
{
private FileStream m_FileStream;
private StreamWriter m_StreamWriter;
private object m_Lock = new object();
void CreateNewLogFile()
{
lock (m_Lock)
{
if ( m_FileStream != null )
m_StreamWriter = new StreamWriter(m_FileStream);
};
}
void CalledFromOtherThread()
{
//Do stuff
lock (m_Lock)
{
if (m_FileStream != null)
m_FileStream.Dispose();
m_FileStream = null;
}
}
}
当从其他线程调用时,它应该获取锁,然后处理m_文件流。这样,在CreateNewLogFile
中,您将永远不会有一个已处理的文件流更好
static void Main()
{
// Thread-Local variable that yields a name for a thread
ThreadLocal<string> ThreadName = new ThreadLocal<string>(() =>
{
return "Thread" + Thread.CurrentThread.ManagedThreadId;
});
// Action that prints out ThreadName for the current thread
Action action = () =>
{
// If ThreadName.IsValueCreated is true, it means that we are not the
// first action to run on this thread.
bool repeat = ThreadName.IsValueCreated;
Console.WriteLine("ThreadName = {0} {1}", ThreadName.Value, repeat ? "(repeat)" : "");
};
// Launch eight of them. On 4 cores or less, you should see some repeat ThreadNames
Parallel.Invoke(action, action, action, action, action, action, action, action);
// Dispose when you are done
ThreadName.Dispose();
}
static void Main()
{
//生成线程名称的线程局部变量
ThreadLocal ThreadName=新的ThreadLocal(()=>
{
返回“Thread”+Thread.CurrentThread.ManagedThreadId;
});
//打印当前线程的ThreadName的操作
动作动作=()=>
{
//如果ThreadName.IsValueCreated为true,则表示我们不是
//在此线程上运行的第一个操作。
bool repeat=ThreadName.IsValueCreated;
WriteLine(“ThreadName={0}{1}”,ThreadName.Value,repeat?”(repeat)”:“”);
};
//启动其中八个。在4个内核或更少的内核上,您应该会看到一些重复的线程名称
并行调用(动作,动作,动作,动作,动作,动作,动作,动作,动作);
//完成后处理
ThreadName.Dispose();
}
这一点更好
static void Main()
{
// Thread-Local variable that yields a name for a thread
ThreadLocal<string> ThreadName = new ThreadLocal<string>(() =>
{
return "Thread" + Thread.CurrentThread.ManagedThreadId;
});
// Action that prints out ThreadName for the current thread
Action action = () =>
{
// If ThreadName.IsValueCreated is true, it means that we are not the
// first action to run on this thread.
bool repeat = ThreadName.IsValueCreated;
Console.WriteLine("ThreadName = {0} {1}", ThreadName.Value, repeat ? "(repeat)" : "");
};
// Launch eight of them. On 4 cores or less, you should see some repeat ThreadNames
Parallel.Invoke(action, action, action, action, action, action, action, action);
// Dispose when you are done
ThreadName.Dispose();
}
static void Main()
{
//生成线程名称的线程局部变量
ThreadLocal ThreadName=新的ThreadLocal(()=>
{
返回“Thread”+Thread.CurrentThread.ManagedThreadId;
});
//打印当前线程的ThreadName的操作
动作动作=()=>
{
//如果ThreadName.IsValueCreated为true,则表示我们不是
//在此线程上运行的第一个操作。
bool repeat=ThreadName.IsValueCreated;
WriteLine(“ThreadName={0}{1}”,ThreadName.Value,repeat?”(repeat)”:“”);
};
//启动其中八个。在4个内核或更少的内核上,您应该会看到一些重复的线程名称
并行调用(动作,动作,动作,动作,动作,动作,动作,动作,动作);
//完成后处理
ThreadName.Dispose();
}
如果您的IDisposable
对象实例已被调用的Dispose()
方法处置,则对象引用将不再可用,或者应该不再可用,因为其内部状态已在挂起垃圾回收期间被破坏
您应该实例化一个新的对象实例,而不是试图重用现有的对象实例
当对已处置对象执行任何操作时,精心编制的对象应抛出的特定子类型:(处置后调用Dispose()
可能除外)
社区内容部分中的文档提供了线程安全实现的一个很好的示例。如果您的IDisposable
对象实例已通过调用其Dispose()
方法处理,对象引用不再可用,或者应该不再可用,因为其内部状态已在挂起垃圾回收时被破坏
您应该实例化一个新的对象实例,而不是试图重用现有的对象实例
当对已处置对象执行任何操作时,精心编制的对象应抛出的特定子类型:(处置后调用Dispose()
可能除外)
社区内容部分中的文档提供了线程安全实现的一个很好的示例。您在哪里分配m_FileStream?您正在创建一个空流。它出现了。。您是否有从问题中遗漏的其他代码..?您在哪里创建初始文件流..?@DJKRAZE-我在上面有它(请参见编辑)看起来仍然会导致错误您在哪里定义或传入m_CurrentFileName..?您在哪里分配m_文件流?您正在创建一个空流它出现。。您是否有从问题中遗漏的其他代码..?您在何处创建初始文件流..?@DJKRAZE-我在上面有它(请参见编辑)看起来仍然会导致错误您在何处定义或传入m_CurrentFileName..?因此调用方应负责调用dispose?调用方应获得锁。这可确保m_文件流为null或有效,因此调用方应负责调用dispose?调用方应获得锁。这将确保m_文件流为null或有效