【问题标题】:How to return thread safe byte[]?如何返回线程安全字节[]?
【发布时间】:2013-07-08 22:04:15
【问题描述】:

很抱歉发布这样一个菜鸟问题,但我找不到答案。我还不太擅长单元测试,所以我不确定。这是返回线程安全的字节 [] 的最佳方法吗?也可以在这里初始化数组并在另一个线程中修改它吗?

public async Task<byte[]> GetData()
{
    var _buffer = new byte[1024];
    try { await Task.Run(() => ModifyArray(_buffer)); }
    catch { return null;}

    return _buffer.ToArray();
}

我知道 ModifyArray(byte[]) 应该返回值,但它实际上是一个 Socket 接收方法。 我也在看:

public async Task<byte[]> GetData()
{
    return Task.Run(() => 
    {
        var _buffer = new byte[1024];
        try { ModifyArray(_buffer); }
        catch { return null;}

        return _buffer.ToArray();
    });
}

或者我应该像这样将 ToArray() 移到外面

public async Task<byte[]> GetData()
{
    return (Task.Run(() => {...});).ToArray();
}

任何见解将不胜感激。

【问题讨论】:

  • 线程不安全代码的标记是一个由一个线程读取并由另一个线程写入的变量。在发布的 sn-p 中没有明显的迹象,_buffer 是一个局部变量,每个线程都有自己的局部变量。我们看不到 ModifyArray() 的作用,它可能是线程不安全的。可能是因为它使用了一个完全未初始化的数组。但正如发布的那样,没有明显的麻烦来源。
  • @HansPassant ModifyArray() 实际上是 Socket 类中的 Receive()。我认为任何线程都可以读取变量但只有一个可以更改它?我写的第二个和第三个代码块有什么区别吗?
  • 线程安全针对什么故障模式?您要避免的问题是什么?我的经验是,没有两个人对“线程安全”有相同的定义,所以如果你想要一个可靠的答案,请更具体。
  • 这与您的问题无关,但是,请不要这样做:catch { return null; }。如果发生了不好的事情,您想尽可能多地了解,因此隐藏您可能拥有的有关错误的任何信息不是一个好主意。

标签: c# .net thread-safety


【解决方案1】:

如果您想返回数组的快照,但又不希望调用者修改您的内部状态,则需要创建数组的副本。

但这不是你的情况。您在方法的每次调用中创建一个新数组,并且您不关心调用者是否修改它(假设 ModifyArray() 不存储该数组)。

这意味着下面的代码应该没问题:

public async Task<byte[]> GetData()
{
    var _buffer = new byte[1024];
    await Task.Run(() => ModifyArray(_buffer));
    return _buffer;
}

另一种选择是使用最接近 .Net 的“只读数组”:IReadOnlyList&lt;T&gt;(.Net 4.5 中的新功能):

public async Task<IReadOnlyList<byte>> GetData()
{
    var _buffer = new byte[1024];
    await Task.Run(() => ModifyArray(_buffer));
    return _buffer;
}

另外,像这样使用await Task.Run()often not a good idea。如果您想充分利用异步,请使用真正的异步方法。如果您想从 UI 线程中卸载一些计算,请在 UI 代码中执行此操作,而不是在您的库中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多