托管Win32函数,完善.NET Compact Framework 线程同步

      .NET CF 2.0虽然加入了一些线程同步的对象,然而,还是没有完整框架中提供的同步功能完善,在我的项目中用到WaitHandle的WaitAny方法时真是一筹莫展,其实我们可以通过托管系统API完善这些我们需要的功能, 通过查阅SDK文档我们得到两个重要的函数WaitForSingleObject和WaitForMultipleObjects, 其中WaitForSingleObject已经由CF中的WaitHandle.WaitOne方法为我们提供了相应的功能,而我们需要的WaitAAny方法可以在WaitForMultipleObjects中找到,为了普遍性,我们以构造WaitAll方法来说明托管API的工作,下面我们来看看WaitForMultipleObjects函数原形:

DWORD WaitForMultipleObjects(
DWORD nCount,
CONST HANDLE* lpHandles,
BOOL fWaitAll,
DWORD dwMilliseconds
);

      SDK是这样描述这个函数的:

Parameters

nCount
[in] Specifies the number of object handles in the array pointed to by lpHandles. The maximum number of object handles is MAXIMUM_WAIT_OBJECTS.
lpHandles
[in] Pointer to an array of object handles. For a list of the object types whose handles can be specified, see the Remarks section. The array can contain handles of objects of different types.
fWaitAll
[in] Specifies the wait type. This parameter must be set to FALSE. This causes function to return when the state of any one of the objects set to is signaled. The return value indicates the object whose state caused the function to return.
dwMilliseconds
[in] Specifies the time-out interval in milliseconds. The function returns if the interval elapses, even if the conditions specified by the bWaitAll parameter are not met. If dwMilliseconds is zero, the function tests the states of the specified objects and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.

Return Values

If the function succeeds, the return value indicates the event that caused the function to return. This value can be one of the following.

        我想不用我在废话了,毕竟我的E文很菜,注意参数dwMilliseconds ,这里说当参数为INFINITE时,将无限等待。我们看看这个函数的头文件Winbase.h, INFINITE的值为0xffffffffL,转为int型就是-1. OK,全部清楚代码就很简单了。

[DllImport("coredll.dll", SetLastError = true)]
public static extern int WaitForMultipleObjects(uint nCount, IntPtr[] lpHandles, bool fWaitAll, Int32 dwMilliseconds);

我们在看看完整框架中WaitAll方法的一个原形:

public static bool WaitAll (
    WaitHandle[] waitHandles,
    TimeSpan timeout,
    bool exitContext
)

似乎不太一样,首先看返回值这里是bool,而我们的API里是bool,其实很简单,.NET中返回True表示已经收到信号,我们在看WaitForMultipleObjects的返回值,他有几种可能,返回WAIT_FAILED,表示函数调用失败,返回WAIT_TIMEOUT表示超时,返回WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount –1)这个是根据第三个参数不同来计算返回lpHandles的索引,为了和完整框架保持一直性,我们这样封装。(通过查看头文件可以找到WAIT_FAILED = -1)

public static bool WaitAll(WaitHandle[] waitHandles, TimeSpan timeout, bool exitContext)
{
   if (waitHandles == null)
   {
      throw new ArgumentNullException();
   }
   System.Collections.Generic.List<IntPtr> array = new System.Collections.Generic.List<IntPtr>();
   foreach (WaitHandle waitHandle in waitHandles)
   {
      if (!array.Contains(waitHandle.Handle))
      {
           array.Add(waitHandle.Handle);
      }
      else
      {
         throw new System.ArgumentException("Pleonastic element exist the array", "waitHandles");
      }
   }
   int res = Core.WaitForMultipleObjects(array.Count, array.ToArray(), true, (int)timeout.TotalMilliseconds);
   return (res != -1)
}

    到这里WaitAll算千呼万唤始出来了,而同样的方法我们只需要把WaitForMultipleObjects函数的第三个参数设为False就可以封装出WaitAny方法,嘿嘿~终于得到了WaitAny方法了。

    最后我们在回到上面带出的SDK文档,注意看WaitForMultipleObjects的第三个参数说明:

fWaitAll
[in] Specifies the wait type. This parameter must be set to FALSE. This causes function to return when the state of any one of the objects set to is signaled. The return value indicates the object whose state caused the function to return.

    文档中提到,这个参数必须为false, 因为我并没有用过WaitAll,所以没去实践我们做法的正确性,然而我只能告诉你可能是文档错了,由于时间有限,只有等有空我再去证实我的想法。
 

你可能感兴趣的:(framework)