C# 程序是否线程安全

C# 程序是否线程安全,c#,C#,我的程序中有一个方法,需要知道它是否是线程安全的。我正在将System.I.O异常写入此文件,尽管它与终止我的程序的文件不太一致 方法之外提到了文件位置 private readonly string fileNameAndPath = @"C:\Apps\TestService\log\Test.txt"; public void LogRequestDetails_SendOrderRequestMethod(Message request, SendOrderRequest quoteR

我的程序中有一个方法,需要知道它是否是线程安全的。我正在将System.I.O异常写入此文件,尽管它与终止我的程序的文件不太一致

方法之外提到了文件位置

private readonly string fileNameAndPath = @"C:\Apps\TestService\log\Test.txt";

public void LogRequestDetails_SendOrderRequestMethod(Message request, SendOrderRequest quoteRequest)
{
    // Create a writer and open the file:
    StreamWriter log;

    if (!File.Exists(fileNameAndPath))
           log = new StreamWriter(fileNameAndPath);
    else
           log = File.AppendText(fileNameAndPath);

    // Write to the file:
    log.WriteLine("=================================");
    log.WriteLine(DateTime.Now);
    log.WriteLine("Price : " + quoteRequest.Price);
    log.WriteLine("QuoteId : " + quoteRequest.QuoteId);
    log.WriteLine("SecurityId : " + quoteRequest.SecurityId);
    log.WriteLine();
    log.WriteLine("Request string : " + request.ToString());
    log.WriteLine("=================================");
    log.WriteLine("\n");

    // Close the stream:
    log.Close();
}
请参阅下面的堆栈跟踪

Application: BestInvest.Select.ShareDealingService.exe

Framework Version: v4.0.30319

Description: The process was terminated due to an unhandled exception.

Exception Info: System.IO.IOException

Stack:



Server stack trace: 

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)

   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)

   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)

   at System.IO.StreamWriter.CreateFile(String path, Boolean append, Boolean checkHost)

   at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize, Boolean checkHost)

   at System.IO.StreamWriter..ctor(String path, Boolean append)

   at System.IO.File.AppendText(String path)

   at BestInvest.Direct.Integration.FIXService.ShareDealingEngine.LogRequestDetails_SendOrderRequestMethod(Message request, SendOrderRequest quoteRequest)

   at BestInvest.Direct.Integration.FIXService.ShareDealingEngine.<>c__DisplayClass5.<SendOrder>b__2()

   at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)

   at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)

   at System.Runtime.Remoting.Proxies.RealProxy.EndInvokeHelper(System.Runtime.Remoting.Messaging.Message, Boolean)

   at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(System.Object, System.Runtime.Remoting.Proxies.MessageData ByRef)

   at System.Action.EndInvoke(System.IAsyncResult)

   at System.Runtime.Remoting.Messaging.AsyncResult.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage)

   at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Messaging.IMessageSink)

   at System.Runtime.Remoting.Proxies.AgileAsyncWorkerItem.ThreadPoolCallBack(System.Object)

   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object)

   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)

   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)

   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()

   at System.Threading.ThreadPoolWorkQueue.Dispatch()

   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

它不是线程安全的。通过使用锁,您可以保护代码的关键部分不受竞争条件的影响

private readonly string fileNameAndPath = @"C:\Apps\TestService\log\Test.txt";

private Object thisLock = new Object();

public void LogRequestDetails_SendOrderRequestMethod(Message request, SendOrderRequest quoteRequest)
{
  lock (thisLock)
  {
     // Create a writer and open the file:
     StreamWriter log;

     if (!File.Exists(fileNameAndPath))
       log = new StreamWriter(fileNameAndPath);
     else
       log = File.AppendText(fileNameAndPath);

     // Write to the file:
     log.WriteLine("=================================");
     log.WriteLine(DateTime.Now);
     log.WriteLine("Price : " + quoteRequest.Price);
     log.WriteLine("QuoteId : " + quoteRequest.QuoteId);
     log.WriteLine("SecurityId : " + quoteRequest.SecurityId);
     log.WriteLine();
     log.WriteLine("Request string : " + request.ToString());
     log.WriteLine("=================================");
     log.WriteLine("\n");

     // Close the stream:
     log.Close();
 }
}
有关更多详细信息,请参阅参考资料: 我认为File.Exists和File.AppendText是线程安全的,因为它们是静态调用

但是,对StreamWriter.WriteLine的实例方法调用不会如此,因此我认为一个线程可能正在写入文件,而另一个线程可能在第一个线程完成之前尝试追加,这可能会导致异常

或者实际上,两个线程可以尝试同时使用StreamWriter写入文件


System.IOException上的确切消息是什么?

如果两个线程同时调用该方法会怎么样?在这种情况下,您可能会得到混乱的两个日志记录,例如,第一个线程写入3行,然后第二个线程写入2行,然后第一个agianI在上面添加了堆栈跟踪