[英]Sharing network files for writing and reading
我在C#.NET 3.5中開發了客戶端服務器應用程序。 該應用程序使用3個程序來完成所需的工作。 進程A(服務器)和進程B(遠程啟動器)是在.NET中開發的,進程C是第三方控制台應用程序,其開發語言未知。 使用遠程計算機的管理憑據,進程A在其上復制進程B,並將進程B安排為遠程計算機上的任務。 此后,進程B由任務計划程序啟動,並創建log.txt
文件來記錄消息。 然后,進程B使用Process.Start()
語義啟動進程C,並重定向其standard output and error
以寫入log.txt
文件。 進程A使用Process.GetProcesses(remotecomputername)
語義來監視進程C是否仍在遠程計算機上運行。 進程A還使用網絡共享讀取\\\\RemoteComputerName\\C$\\RemoteDir\\log.txt
讀取log.txt
文件,並在其窗口中顯示消息。
我的問題是,所有輸出和錯誤都未登錄到log.txt
。 並且進程A無法從log.txt
正確讀取。 如果使用DebugView記錄了輸出/錯誤,則說明它們已正確記錄。是否存在同步/訪問權限問題? 如何擺脫它? 任何指針/提示將是真正有價值的。 由於限制,無法共享完整代碼。
下面給出示例代碼
工序A
//Below method is called every 2 seconds from Server to read new messages.
//path passed as `\\RemoteComputerName\C$\RemoteDir\log.txt`
private void ReadRemoteLog(string path)
{
try
{
string[] lines = File.ReadAllLines(path);
while (RemoteLogPosition < lines.LongLength)
{
string msg = lines[RemoteLogPosition].Trim();
if (!string.IsNullOrEmpty(msg))
{
Trace.WriteLine("# " +msg); //Writing on DebugView
OnProgressChanged(msg);
}
RemoteLogPosition++; //This is global variable to keep track of last read position.
}
}
}
流程B的代碼,用於啟動流程C
ProcessStartInfo ps = new ProcessStartInfo();
ps.UseShellExecute = false;
ps.FileName = <Path to process C>;
ps.Arguments = <Commandline args to Process C>;
ps.WorkingDirectory = @"C:\RemoteDir";
ps.RedirectStandardError = true;
ps.RedirectStandardOutput = true;
Process p = new Process();
p.StartInfo = ps;
p.OutputDataReceived += (s, e) => { WriteLog(e.Data.Trim());};
p.ErrorDataReceived += (s, e) => { WriteLog(e.Data.Trim()); };
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
WriteLog("Process Started - "+ps.FileName + ps.Arguments);
p.WaitForExit();
進程B的WriteLog方法-
private void WriteLog(string message)
{
using (FileStream fs = new FileStream(@"C:\\RemoteDir\log.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Inheritable))
using(StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine("#" + message);
}
}
請記住,文件寫入時會獲得排他鎖。 因此,如果兩個線程同時寫入,則其中一個將陷入異常。 閱讀不是問題。 簡單的解決方案是制作多個日志文件或使用數據庫。 另一種方法是保持消息累積並在一個小時內或消息達到100條時寫入一次。 制作字符串列表
List<string> messagelst= new List<string>();
private void WriteLog(string message)
{
messagelst.Add("New York");
messagelst.Add("Mumbai");
messagelst.Add("Berlin");
messagelst.Add("Istanbul");
if(messagelst.length==100){
string message= string.Join(",", messagelst.ToArray());
using (FileStream fs = new FileStream(@"C:\\RemoteDir\log.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Inheritable))
using(StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine("#" + message);
}
messagelst= new List<string>();
}
}
另一種方法是寫異步。 您可能會松動順序。
static Task ProcessWrite()
{
string filePath = @"c:\temp2\temp2.txt";
string text = "Hello World\r\n";
return WriteTextAsync(filePath, text);
}
static async Task WriteTextAsync(string filePath, string text)
{
byte[] encodedText = Encoding.Unicode.GetBytes(text);
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Append, FileAccess.Write, FileShare.None,
bufferSize: 4096, useAsync: true))
{
await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
};
}
簡短的答案: File.ReadAllLines
將不允許其他進程寫入文件。 相關的SO問題有一些解決方法: File.ReadLines是否未鎖定?
這一事實ReadAllLines
正在打開與該文件FileShare.Read
可以通過查看.NET參考的源代碼中找到: https://referencesource.microsoft.com/#mscorlib/system/io/file.cs,5150c565446cd5fd
通過跟蹤呼叫,最終將達到:
Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost);
FileShare.Read
說
允許隨后打開文件進行讀取。 如果未指定此標志,則打開文件以進行讀取的任何請求(通過此過程或其他過程)都將失敗,直到關閉文件為止。
即使ReadAllLines
將關閉文件,在讀取過程中,該文件也不可供其他進程寫入。
本質上,您需要使用FileShare.ReadWrite
(在進程A中)打開文件,以允許另一個進程(您的進程C)繼續寫入此文件。
您可以在寫入文件時嘗試將對象用作鎖:
private static object fileLock = new Object();
現在在WriteLog
方法中:您可以使用lock(fileLock) {}
使用using來處理流。
您也可以看看EventWaitHandle 。 它允許為每個進程創建一個等待句柄的實例。
var wait = new EventWaitHandle(true, EventResetMode.AutoReset, "Common_to_all_process");
然后,在第一個進程完成后,可以通過發出信號將其傳遞到下一個進程:
wait.WaitOne();
/* write to the file*/
wait.Set();
可以將GUID用於“ Common_to_all_process”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.