C# 如何在c程序中连续运行函数
我正在使用为Windows8编写的桌面应用程序,在C#中提供剪贴板上不同设备传感器的读数。 现在,有一个外部应用程序(我无法控制它的结构)将与我的应用程序进行交互。这两个应用程序都使用一个相互文本文件作为开关。 当外部应用程序需要我的读数时,它会将文本文件重命名为“SensorsTurn.txt”,并在剪贴板上放置一个触发字,例如(“sensors”) 当我的应用程序看到文件被命名为这样的文件时,它会读取剪贴板中的触发器,相应地收集数据,将其放在剪贴板上,并将文本文件重命名回“RBsTurn.txt”。 问题是,我需要我的程序在文件运行期间不断检查文件名。我想到的一个非常基本的方法是将程序放入无限while循环。但这显然是一个非常糟糕的方法。当我在任务管理器中看到我的应用程序时,它占用了本不应该占用的大量CPU处理。 我发现的另一个建议是将我的循环设为后台线程,这样效率会高一些。但是两次连续读数之间的时间变慢了。我工作的那个人报告说: “我第一次尝试写入剪贴板时,它写入速度非常快,但在随后的写入过程中大约需要3秒钟(我经常让两个程序与剪贴板通信)。 我怀疑你的程序没有以某种方式释放剪贴板。 一旦我能够写入剪贴板,我就会更改文件名并立即取回您的数据。 因此,问题源于剪贴板写入……” 以下是代码的一部分:C# 如何在c程序中连续运行函数,c#,.net,windows-8,desktop-application,clipboard,C#,.net,Windows 8,Desktop Application,Clipboard,我正在使用为Windows8编写的桌面应用程序,在C#中提供剪贴板上不同设备传感器的读数。 现在,有一个外部应用程序(我无法控制它的结构)将与我的应用程序进行交互。这两个应用程序都使用一个相互文本文件作为开关。 当外部应用程序需要我的读数时,它会将文本文件重命名为“SensorsTurn.txt”,并在剪贴板上放置一个触发字,例如(“sensors”) 当我的应用程序看到文件被命名为这样的文件时,它会读取剪贴板中的触发器,相应地收集数据,将其放在剪贴板上,并将文本文件重命名回“RBsTurn.t
namespace sampleApplication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Initialize sensor variables
LightSensorReading _newLightSensorReading;
LightSensor _LightSensor = LightSensor.GetDefault();
string _pathString = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "dummy");
private void Form1_Load(object sender, EventArgs e)
{
//InitializeDevices();
System.IO.Directory.CreateDirectory(_pathString);
string _filePathSensors = System.IO.Path.Combine(_pathString, "SensorsTurn.txt");
string _filePathRBsTurn = System.IO.Path.Combine(_pathString, "RBsTurn.txt");
string _triggerString = "";
int x = 1;
Thread th = new Thread(() =>
{
while (x == 1)
{
if (System.IO.File.Exists(_filePathSensors))
{
_triggerString = Clipboard.GetText();
switch (_triggerString)
{
case "sensors":
if (_LightSensor != null)
{
_newLightSensorReading = _LightSensor.GetCurrentReading();
string _deviceReading = "LightSensor" + "," + _newLightSensorReading.IlluminanceInLux.ToString();
Clipboard.SetText(_deviceReading);
System.IO.File.Move(_filePathSensors, _filePathRBsTurn);
}
break;
case "stop":
Clipboard.Clear();
System.IO.File.Move(_filePathSensors, _filePathRBsTurn);
Application.Exit();
break;
}
}
}
});
th.IsBackground = true;
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
}
}
长话短说,有两个问题:
1) 如何在不使用效率低下的无限循环的情况下连续检查文件名?我能以某种方式定义一个事件吗??
2) 使用剪贴板后,我的程序释放剪贴板的速度不够快。原因可能是什么?只需使用一个无限循环,但在循环结束时,添加一个
线程。Sleep(1000)
或类似的东西。这样它就不会占用你所有的CPU时间。将数字调整到所需的检查频率。只需使用无限循环,但在循环结束时,添加一个线程。Sleep(1000)
或类似的内容。这样它就不会占用你所有的CPU时间。将数字调整到所需的检查频率。让线程调用包含while循环的方法。让线程调用包含while循环的方法。您可以使用对象响应事件,而不是不断寻找更改的名称。这可能会完全避免这个问题
更新:
下面是一个(前面在评论中提到的)主题您可以使用一个对象来响应事件,而不是不断寻找更改的名称。这可能会完全避免这个问题 更新: 这里有一个(之前在评论中提到的)关于这个主题的我会用一个。这样,您可以按指定的时间间隔运行,否则不会占用CPU。本质上,它完成了Thread.Sleep的线程解决方案所做的事情,但是以一种更干净、更可读的方式,IMHO
using System;
using System.Timers;
public class Timer1
{
private static System.Timers.Timer aTimer;
public static void Main()
{
// Normally, the timer is declared at the class level,
// so that it stays in scope as long as it is needed.
// If the timer is declared in a long-running method,
// KeepAlive must be used to prevent the JIT compiler
// from allowing aggressive garbage collection to occur
// before the method ends. You can experiment with this
// by commenting out the class-level declaration and
// uncommenting the declaration below; then uncomment
// the GC.KeepAlive(aTimer) at the end of the method.
//System.Timers.Timer aTimer;
// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(10000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 2 seconds (2000 milliseconds).
aTimer.Interval = 2000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
// If the timer is declared in a long-running method, use
// KeepAlive to prevent garbage collection from occurring
// before the method ends.
//GC.KeepAlive(aTimer);
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}
/* This code example produces output similar to the following:
Press the Enter key to exit the program.
The Elapsed event was raised at 5/20/2007 8:42:27 PM
The Elapsed event was raised at 5/20/2007 8:42:29 PM
The Elapsed event was raised at 5/20/2007 8:42:31 PM
...
*/
我会用一个。这样,您可以按指定的时间间隔运行,否则不会占用CPU。本质上,它完成了Thread.Sleep的线程解决方案所做的事情,但是以一种更干净、更可读的方式,IMHO
using System;
using System.Timers;
public class Timer1
{
private static System.Timers.Timer aTimer;
public static void Main()
{
// Normally, the timer is declared at the class level,
// so that it stays in scope as long as it is needed.
// If the timer is declared in a long-running method,
// KeepAlive must be used to prevent the JIT compiler
// from allowing aggressive garbage collection to occur
// before the method ends. You can experiment with this
// by commenting out the class-level declaration and
// uncommenting the declaration below; then uncomment
// the GC.KeepAlive(aTimer) at the end of the method.
//System.Timers.Timer aTimer;
// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(10000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 2 seconds (2000 milliseconds).
aTimer.Interval = 2000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
// If the timer is declared in a long-running method, use
// KeepAlive to prevent garbage collection from occurring
// before the method ends.
//GC.KeepAlive(aTimer);
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}
/* This code example produces output similar to the following:
Press the Enter key to exit the program.
The Elapsed event was raised at 5/20/2007 8:42:27 PM
The Elapsed event was raised at 5/20/2007 8:42:29 PM
The Elapsed event was raised at 5/20/2007 8:42:31 PM
...
*/
正确的做法是创建一个事件,当文件名发生更改时(或者创建了一个新文件,文档中对此进行了解释),该事件将引发一个事件
创建/重命名文件时,将触发一个事件,您可以在处理程序的主体中处理并执行操作。正确的做法是创建一个事件,该事件将在文件名更改(或创建了一个新文件-文档中对此进行了解释)时引发事件
创建/重命名文件时,将触发一个事件,您可以在处理程序的主体中处理并执行您的操作。非常好-我不知道这一个。嘿,瑞克,这正是我要找的。请详细说明你的方法或者给我一些链接好吗?PS:这也会对剪贴板问题进行排序吗?@ShobhanTaparia-在另一个SO答案中使用该类处理各种事件。至于剪贴板的问题,我对你的具体情况还不太了解,所以不能说。@ShobhanTaparia-除此之外,还有一些简单的代码示例。很好-我不知道这个问题。嘿,瑞克,这正是我要找的。请详细说明你的方法或者给我一些链接好吗?PS:这也会对剪贴板问题进行排序吗?@ShobhanTaparia-在另一个SO答案中使用该类处理各种事件。至于剪贴板的问题,我对您的具体情况了解得不够多,不能说。@ShobhanTaparia-除此之外,还有一些简单的代码示例。让我试试这个。。它也能帮我解决剪贴板问题吗?老实说,我不知道。但是,如果另一个人也使用FileSystemWatcher,那么首先就不需要使用剪贴板了。一切都是事件驱动的。让我试试这个。。它也能帮我解决剪贴板问题吗?老实说,我不知道。但是,如果另一个人也使用FileSystemWatcher,那么首先就不需要使用剪贴板了。一切都是事件驱动的。(ab)像这样使用剪贴板是个糟糕的主意。(ab)像这样使用剪贴板是个糟糕的主意。