使用VB.Net(Framework 4.5.1版)
我有一个程序设置一个(System.Threading.Tasks.Task)任务列表,执行如下(只显示相关代码):
po = New System.Threading.Tasks.ParallelOptions()
po.MaxDegreeOfParallelism = 5
Parallel.ForEach( task_list, po, AddressOf do_work )
该程序运行正常,但我想添加一个日志文件而不是仅使用Console.WriteLine()
在do_work()Sub中,我想写入日志文件,例如:
Sub do_work( param As String )
Dim thread_id as String = "Thread ID " & System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() & ": "
joblog_append( thread_id & "Beg" )
joblog_append( thread_id & "param = " & param )
joblog_append( thread_id & "End" )
End Sub
理想情况下,我想创建三个函数,例如:
joblog_open()在程序开始时打开一个日志文件。
joblog_append()追加到日志文件;可以在任何任务中调用
joblog_close()关闭日志文件
当从在不同线程上执行的多个任务调用joblog_append()时,实现此类日志记录的正确方法是什么?
到目前为止我尝试过的所有尝试似乎都被击中了;有时数据会写入输出文件,有时则不会。
任何建议(或者更好的是代码示例)都会受到最高的赞赏。
提前致谢。
答案 0 :(得分:1)
我认为您遇到的问题是由于多个线程同时访问该文件。
更好的方法是确保一次只有一个线程访问该文件。您可以使用锁(请参阅this SO)或将要写入的消息附加到string的concurrentQueue,然后在另一个线程上处理该队列。
joblog_append 调用_Logger.Log,后者依次将消息入队并启动新线程来处理队列。
private _Logger as new Logger
Private Sub joblog_append(Message As String)
_Logger.Log(Message)
End Sub
logger类执行以下操作。
如果已经创建了任务,则该消息将被排队,并且任务本身中的While条件应该处理在其运行时添加的任何消息。
'Missing: Idisposable, Fileaccess.Shared,
'TODO: remove debugger.break
Public class Logger
Public Property Messages As new ConcurrentQueue(Of string)
private _WorkerTask as Task
private event WorkerTaskCompleted
private _Stream as FileStream
private _Writer as StreamWriter
Public sub New()
_Stream = io.file.OpenWrite("Mylog.txt")
_Writer = New StreamWriter(_Stream)
End sub
Public sub Log(Message as string)
Messages.Enqueue(Message)
if _WorkerTask Is Nothing
_WorkerTask = New Task(sub()
While Messages.Any
Dim CurrentMessage as string = ""
if Messages.TryDequeue(CurrentMessage)
_Writer.WriteLine(CurrentMessage)
else
debugger.Break
End If
End While
_Writer.Flush
_Stream.Flush
RaiseEvent WorkerTaskCompleted
End Sub)
_WorkerTask.Start
End If
End sub
Private Sub Logger_WorkerTaskCompleted() Handles Me.WorkerTaskCompleted
_WorkerTask = Nothing
End Sub
End Class
请注意。这是我解决这个问题的方法,但我没有任何类似的实现和测试。因此,您必须进行测试以确认它是否正常工作。