.net - 在多线程环境中使用TraceSource

标签 .net asynchronous f# trace tracesource

我使用异步工作流在 F# 中编写了一个应用程序。 现在我想做的是添加一些跟踪!

基本上有一个可以多次实例化的 A 类。每个实例都独立异步(本身)和并行(与其他实例)工作。 我现在的基本想法是为 A 的每个实例添加一个 TraceSource 实例,这很可能是我想要做的。我设法通过 https://github.com/matthid/fsharpasynctrace 解决了使用 Async 对象分发 TraceSource 的问题

但是,如果每个 TraceSource 实例都指定相同的名称,则其中一些实例将写入同一个文件 (log.txt),而其他实例将写入 {guid}log.txt。

如果我为每个实例指定一个其他名称,则用户必须编辑 app.config 文件才能正确记录日志。 A 的每个实例都有一个由用户指定的逻辑名称,因此理想情况下我会将实例的日志保存在 name_log.txt 中。 (这是因为用户基本上是在运行时创建 A 的实例)

所以我的问题是:有没有更好的方法来做到这一点,即无需用户交互,仍然可以获得所需的输出和灵活性(通过 app.config)?

注意:因为基本上所有内容都在线程池中,并且因为同时跨实例可能有很多操作,所以跟踪类或线程根本不是一个选项。

注2:我可以考虑以某种方式扩展app.config并自己完成,这是我唯一的选择吗?

编辑: 为了使问题更清楚:

想象一下下面的类:

module OtherModule = 
    let doSomethingAsync m = async{return()}
[<AbstractClass>]
type A (name:string) as x = 
    let processor = 
        MailboxProcessor.Start(
            fun inbox -> async {
                while true do
                    let! msg = inbox.Receive()
                    do! x.B(msg)
                    do! OtherModule.doSomethingAsync(msg)})
    abstract member B : string -> Async<unit>
    member x.Do(t:string) = processor.Post(t)

您有很多此类的实例,并且每个实例的生命周期都很长。您现在遇到了上述情况。 (您还想跟踪抽象成员,这可以通过 protected 跟踪源来完成...这在 F# 中不可用。并且您想跟踪一些模块函数。这就是我选择上述分发模型的原因。如果您这样做任何其他方式你都将很难浏览日志。)

最佳答案

我还没有测试过这个,但看起来它会起作用。 TraceSource 上的 TraceXXX 方法接受 id 参数。将其用作“实例标识符”怎么样?然后,您可以编写一个自定义跟踪监听器来根据该 ID 重定向输出。也许这将作为一个起点:

type MultiOutputTraceListener(directory) =
  inherit TraceListener()

  let mutable output : TextWriter = null
  let writers = Dictionary()

  let setOutput (id: int) =
    lock writers <| fun () ->
      match writers.TryGetValue(id) with
      | true, w -> output <- w
      | _ ->
        let w = new StreamWriter(Path.Combine(directory, id.ToString() + ".log"))
        writers.Add(id, w)
        output <- w

  override x.Write(msg: string) = output.Write(msg)
  override x.WriteLine(msg: string) = output.WriteLine(msg)

  override x.TraceData(eventCache, source, eventType, id, data: obj) =
    setOutput id
    base.TraceData(eventCache, source, eventType, id, data)

  override x.TraceData(eventCache, source, eventType, id, data) =
    setOutput id
    base.TraceData(eventCache, source, eventType, id, data)

  override x.TraceEvent(eventCache, source, eventType, id, message) =
    setOutput id
    base.TraceEvent(eventCache, source, eventType, id, message)

  override x.TraceEvent(eventCache, source, eventType, id, format, args) =
    setOutput id
    base.TraceEvent(eventCache, source, eventType, id, format, args)

  override x.Dispose(disposing) =
    if disposing then
      for w in writers.Values do
        w.Dispose()

使用

module Tracing =
  let Source = TraceSource("MyTraceSource")

type A(id) =
  member x.M() =
    Tracing.Source.TraceEvent(TraceEventType.Verbose, id, "Entering method M()")
    ...

let a1 = A(1)
let a2 = A(2)

关于.net - 在多线程环境中使用TraceSource,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11397654/

相关文章:

c# - 更新 DataTable 中的行 - 为什么这不起作用?

c# - 是否可以构建一个二叉树并跟踪中位数,仍然使用 O(log(n)) 插入?

c# - E pluribus unum : merge objects into one

java - 等待任务完成而不阻塞 javafx 中的 UI

f# - 如何在F#中以复合类型覆盖ToString?

c# - Processcmdkey 中的可访问性不一致错误

java - Android - 如何在 Volley 请求后重新加载数据

c# - 对异步 WCF 的所有其他调用都很慢

用于构建状态和延迟执行的 F# 计算表达式

command-line - 如何忽略命令行参数中的转义字符?