介绍
这是一个很长的问题!您将在开始时找到有关问题的一些背景,然后是代码示例,这些示例已被简化以用于表示和之后的问题。请按照您认为适合您的任何顺序阅读!
背景资料
我正在为与 STA COM 通信的应用程序编写概念验证部分。这部分应用程序需要在单线程单元 (STA) 上下文中运行,以便与所述 STA COM 通信。应用程序的其余部分在 MTA 上下文中运行。
当前状态
到目前为止,我想出的是创建一个包含循环的通信类,在 STA 中运行。while需要中继到 COM 对象的工作从外部通过ConcurrentQueue. 然后工作项在 while 循环中出列并执行工作。
代码上下文
通讯类
这是一个static类,包含一个循环,旨在在 STA 状态下运行并检查是否需要由 COM 完成某些工作并将工作分派给处理程序。
static class Communication
{
#region Public Events
/// This event is raised when the COM object has been initialized
public static event EventHandler OnCOMInitialized;
#endregion Public Events
#region Private Members
/// Stores a reference to the COM object
private static COMType s_comObject;
/// Used to queue work that needs to be done by the COM object
private static ConcurrentQueue<WorkUnit> s_workQueue;
#endregion Private Members
#region Private Methods
/// Initializes the COM object
private static void InternalInitializeCOM()
{
s_comObject = new COMType();
if (s_comObject.Init())
{
OnCOMInitialized?.Invoke(null, EventArgs.Empty);
}
}
/// Dispatches the work unit to the correct handler
private static void HandleWork(WorkUnit work)
{
switch (work.Command)
{
case WorkCommand.Initialize:
InternalInitializeCOM();
break;
default:
break;
}
}
#endregion Private Methods
#region Public Methods
/// Starts the processing loop
public static void StartCommunication()
{
s_workQueue = new ConcurrentQueue<WorkUnit>();
while (true)
{
if (s_workQueue.TryDequeue(out var workUnit))
{
HandleWork(workUnit);
}
// [Place for a delaying logic]
}
}
/// Wraps the work unit creation for the task of Initializing the COM
public static void InitializeCOM()
{
var workUnit = new WorkUnit(
command: WorkCommand.Initialize,
arguments: null
);
s_workQueue.Enqueue(workUnit);
}
#endregion Public Methods
}
工作指挥
此类描述需要完成的工作以及可能提供的任何参数。
enum WorkCommand
{
Initialize
}
工作单位
此枚举定义了 COM 可以执行的各种任务。
class WorkUnit
{
#region Public Properties
public WorkCommand Command { get; private set; }
public object[] Arguments { get; private set; }
#endregion Public Properties
#region Constructor
public WorkUnit(WorkCommand command, object[] arguments)
{
Command = command;
Arguments = arguments == null
? new object[0]
: arguments;
}
#endregion Constructor
}
所有者
这是拥有或生成CommunicationCOM 的类的示例,并且是对应用程序其余部分使用的抽象Communication。
class COMController
{
#region Public Events
/// This event is raised when the COM object has been initialized
public event EventHandler OnInitialize;
#endregion Public Events
#region Constructor
/// Creates a new COMController instance and starts the communication
public COMController()
{
var communicationThread = new Thread(() =>
{
Communication.StartCommunication();
});
communicationThread.SetApartmentState(ApartmentState.STA);
communicationThread.Start();
Communication.OnCOMInitialized += HandleCOMInitialized;
}
#endregion Constructor
#region Private Methods
/// Handles the initialized event raised from the Communication
private void HandleCOMInitialized()
{
OnInitialize?.Invoke(this, EventArgs.Emtpy);
}
#endregion Private Methods
#region Public Methods
/// Requests that the COM object be initialized
public void Initialize()
{
Communication.InitializeCOM();
}
#endregion Public Methods
}
问题
现在,看一下Communication.StartCommunication()方法,更具体地说是这部分:
...
// [Place for a delaying logic]
...
如果此行替换为以下内容:
await Task.Delay(TimeSpan.FromMilliseconds(100)).ConfigureAwait(false);
// OR
await Task.Delay(TimeSpan.FromMilliseconds(100)).ConfigureAwait(true);
在检查最后一站 -Communication.InternalInitializeCOM()线程的公寓似乎是MTA。
但是,如果延迟逻辑更改为
Thread.Sleep(100);
该CommunicationInternalInitializeCOM()方法似乎在STA状态下执行。
检查由Thread.CurrentThread.GetApartmentState().
问题
谁能向我解释为什么会Task.Delay破坏 STA 状态?还是我在这里做其他错误的事情?
谢谢!
感谢您抽出所有时间阅读问题!祝你有美好的一天!