1

我使用以下代码导入“winmm.dll”。

  MyUtils = public static class
  private
  protected
  public
    [DllImport("winmm.dll")]
    class method timeBeginPeriod(period:Integer):Integer; external;
    [DllImport("winmm.dll")]
    class method timeEndPeriod(period:Integer):Integer; external;
  end;

访问方法如下。

MyUtils.timeBeginPeriod(1); //within winform load event
MyUtils.timeEndPeriod(1);   //within winform formclosing event

在 Windows 7 下,它按预期工作得很好。在 Linux 系统上的 mono 下,它也可以正常工作,但有一个例外。程序启动后,会弹出一个消息框,其中包含导入的 dll 的名称和 OK 按钮,如下所示。当我单击“确定”按钮时,我的程序继续并按预期运行,没有任何错误。

在此处输入图像描述

我已经梳理了我的程序,看看我是否有意在任何地方显示 dll 文件名,但我根本找不到类似的东西。

编辑:更多信息,我需要使用 winmm.dll 的原因是我需要能够将线程睡眠粒度或默认延迟调整到大约 1 毫秒或接近它 -不要播放电影或音乐文件。我能够调整的唯一方法是通过这些方法timeBeginPeriodtimeEndPeriod. 这样我的程序就可以通过串口成功通话了。我的程序是每隔几毫秒来回交谈一次,24/7/365 天不间断。至关重要的是,它的通信达到 90% 或更多。导入 dll 文件后,我的程序在 windows 和 linux 上的通信是完美的,除了我在单声道下的 Linux 上得到那个烦人的消息框。

我以前从未见过或听说过这样的问题。有人为什么吗?

谢谢,

4

1 回答 1

4

我认为对 Mono 的工作方式存在一些误解。WinMM.dll 是 Windows 的本机二进制文件。Mono 不会自动允许您导入 winmm.dll 并在 linux 环境中使用它。我猜你的程序没有按预期运行,因为timeBeginPeriodandtimeEndPeriod不会执行。

除非您有一些适用于 linux 的 Windows 多媒体模块的端口,否则这是行不通的。Mono 移植了System.Media.SoundPlayer有什么方法可以从中获得所需的一切吗?

Mono 中的 P/Invoke 运行良好,但您仍然需要为每个平台本地构建二进制文件。

有一篇感兴趣的文章关于移植到 linux - 替换 winmm

您可能想查看 LGPL LAME

更新

问题是 Thread.sleep 不是一个准确的等待来创建确定性行为,而不管分辨率如何。您不能使用 Thread.sleep 以接近 1ms 的粒度同步某些内容。JVM 和 .NET 平台都可以达到接近 1ms 的精度,但是这并不能保证。如果系统很忙,您可能无法及时将上下文切换回您的线程,这意味着它可能是 3 毫秒、10 毫秒,甚至更糟糕的是 30 毫秒。

您应该搜索两件事。Linux 上的高分辨率计时器。以及如何创建实时系统。由于您几乎需要与毫秒通信,因此您需要研究实时系统并弄清楚如何创建一个确定性的计时系统。

大多数计时器只能让您获得接近 30 毫秒的分辨率。

如果您在 linux 上找到高分辨率计时器,您仍然需要考虑上下文切换和时间流逝以弥补丢失的时间,或者在亚毫秒处理时减慢速度。

我意识到您声称它在 Windows 上运行良好,但我试图解释它并没有真正按照您的想法工作。它现在可以工作,但是在该机器上可能会出现许多情况,这将导致您的系统无法以 1 毫秒的间隔处理数据,因此需要您在以后调试系统。

支持我的一些事情:如何在 Windows 上使线程睡眠时间少于一毫秒

于 2012-11-01T16:26:19.260 回答