[英]Events and the DriveInfo class
我有一個類具有DriveInfo類型的屬性,您可能已經知道,該類具有IsReady的布爾屬性。 這是代表驅動器何時“就緒”的值-對我來說,這意味着驅動器中有CD,因為我僅選擇了CDRom驅動器。
我想做的就是在屬性更新時調用一個事件-當前,我正在實例化該對象,然后執行while循環以等待該值為真。
public bool WaitUntilReady()
{
while (!Cancelled)
{
if (Drive.IsReady) return true;
}
return false;
}
我更喜歡一種方法或類似的方法。 謝謝。
如果您正在等待設備狀態的更改(例如CD插入/取出),則收聽WM_DEVICECHANGE
消息將是更好的方法。
Windows發送所有頂級窗口一組默認的
WM_DEVICECHANGE
消息時添加新的設備或介質(如CD或DVD),並成為可用,並移除現有的設備或媒體時... 閱讀更多
嘗試使用以下幫助程序類來偵聽媒體的插入/刪除:
DriveHelper
public static class DriveHelper
{
const int WM_DEVICECHANGE = 0x0219;
const int DBT_DEVICEARRIVAL = 0x8000;
const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
const int DBT_DEVTYP_VOLUME = 0x00000002;
const ushort DBTF_MEDIA = 0x0001;
[StructLayout(LayoutKind.Sequential)]
struct DEV_BROADCAST_VOLUME
{
public uint dbch_Size;
public uint dbch_Devicetype;
public uint dbch_Reserved;
public uint dbch_Unitmask;
public ushort dbch_Flags;
}
public class StateChangedEventArgs : EventArgs
{
public StateChangedEventArgs(string drive, bool ready)
{
Drive = drive;
Ready = ready;
}
public string Drive { get; private set; }
public bool Ready { get; private set; }
}
public static void QueryDeviceChange(Message m, Action<StateChangedEventArgs> action)
{
if (action == null || m.Msg != WM_DEVICECHANGE) return;
var devType = Marshal.ReadInt32(m.LParam, 4);
if (devType != DBT_DEVTYP_VOLUME) return;
var lpdbv = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
if (lpdbv.dbch_Flags != DBTF_MEDIA) return;
var eventCode = m.WParam.ToInt32();
var drive = GetFirstDriveFromMask(lpdbv.dbch_Unitmask);
switch (eventCode)
{
case DBT_DEVICEARRIVAL:
action(new StateChangedEventArgs(drive, true));
break;
case DBT_DEVICEREMOVECOMPLETE:
action(new StateChangedEventArgs(drive, false));
break;
}
}
static string GetFirstDriveFromMask(uint mask)
{
int i;
for (i = 0; i < 26; ++i)
{
if ((mask & 0x1) == 0x1)
break;
mask = mask >> 1;
}
return string.Concat((char)(i + 65), @":\");
}
}
使用示例 (適用於Windows Forms
應用)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
void OnStateChanged(DriveHelper.StateChangedEventArgs e)
{
// do your work here
MessageBox.Show(string.Format("Drive: {0} => e.Ready: {1}, DriveInfo.IsReady: {2}", e.Drive, e.Ready, new DriveInfo(e.Drive).IsReady));
}
protected override void WndProc(ref Message m)
{
DriveHelper.QueryDeviceChange(m, OnStateChanged);
base.WndProc(ref m);
}
}
如果我正確理解了您的問題,則希望在插入CD / DVD時得到通知。 因此,這可能會有所幫助: 檢測CD-ROM插入
我認為這可以解決您的WMI問題。
如果您希望每隔x個timeunins進行一次呼叫,則可以在任務和異步/等待的幫助下執行以下操作:
var cts = new CancellationTokenSource();
var token = cts.Token;
Task yourTask = Task.Factory.StartNew(async () =>
{
while (true)
{
// run in a loop until aborted
if (token.IsCancellationRequested)
break;
// do your request here ...
// wait
await Task.Delay(theTimeIntervalToWait, token);
}
}, token);
然后可以使用cts.Cancel();
中止您的任務(從外部)。 如果要確保已完成,則可以調用yourTask.Wait()
。
一般來說,在大多數情況下,您不應該使用while(true) { permanently-polling }
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.