程序是Threadsafe还是不是c#

时间:2015-11-13 12:51:42

标签: c#

我的程序中有一个方法,需要知道它是否是线程安全的。我收到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()

2 个答案:

答案 0 :(得分:1)

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

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();
 }
}

有关详细信息,请参阅参考资料: https://msdn.microsoft.com/en-us/library/a8544e2s.aspx

答案 1 :(得分:0)

我认为File.ExistsFile.AppendText是线程安全的,因为它们是静态调用。

但是,对StreamWriter.WriteLine的实例方法调用不会这样,我认为一个线程可以写入文件而另一个线程可以在第一个线程完成之前尝试添加这可能导致例外。

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

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