关于异步任务和处理

本文关键字:任务 处理 异步 于异步 | 更新日期: 2023-09-27 18:13:38

在我的MainWindow中,我有一个按钮,可用于打开Process(本地OpenProcess调用)并对其内存执行一些检查,但在Click上调用的方法是异步的:

<Button Content="Attach" Click="OnClickAttach"/>
private async void OnClickAttach(Object sender, RoutedEventArgs e)
{
    AttachmentResult result = await m_ViewModel.Attach();
    switch (result)
        // Different MessageBox depending on the result.
}

现在,让我们看看ViewModel部分的代码…

// MemoryProcess class is just a wrapper for Process' handle and memory regions.
private MemoryProcess m_MemoryProcess;
public async Task<AttachmentResult> Attach()
{
    AttachmentResult result = AttachmentResult.Success;
    MemoryProcess memoryProcess = NativeMethods.OpenProcess(m_SelectedBrowserInstance.Process);
    if (memoryProcess == null)
        result = AttachmentResult.FailProcessNotOpened;
    else
    {
        Boolean check1 = false;
        Boolean check2 = false;
        foreach (MemoryRegion region in memoryProcess)
        {
            // I perform checks on Process' memory regions and I eventually change the value of check1 or check2...
            await Task.Delay(1);
        }
        if (!check1 && !check2)
        {
            NativeMethods.CloseHandle(memoryProcess.Handle);
            result = AttachmentResult.FailProcessNotValid;
        }
        else
        {
            // I keep the Process opened for further use. I save it to a private variable.
            m_MemoryProcess = memoryProcess;
            m_MemoryProcess.Check1 = check1;
            m_MemoryProcess.Check2 = check2;
        }
    }
    return result;
}

现在…问题来了。当用户关闭应用程序时,如果打开了Process,我必须正确关闭其句柄。所以在我的MainWindow中,我有以下代码:

protected override void OnClosing(CancelEventArgs e)
{
    m_ViewModel.Detach();
    base.OnClosing(e);
}

在我的ViewModel中,我有以下代码:

public void Detach()
{
    if (m_MemoryProcess != null)
    {
        if (m_MemoryProcess.Check1)
            // Do something...
        if (m_MemoryProcess.Check2)
            // Do something...
        NativeMethods.CloseHandle(m_MemoryProcess.Handle);
        m_MemoryProcess = null;
    }
}

Attach()方法耗时很长,有时超过2分钟。我需要找到一个解决以下问题的方法:

  • 如果用户在Attach()方法运行时关闭应用程序,并且在memoryProcess被保存到私有变量之前,Process句柄将不会被关闭。
  • 如果我在Attach()方法的开头将MemoryProcess实例保存到私有变量,那么如果在Attach()方法处理foreach循环时关闭应用程序,则用户有可能获得NullReferenceException
  • 我绝对不想让用户在关闭应用程序之前等待Attach()方法完成。这是可怕的。

我该怎么做?

关于异步任务和处理

IMO,如果您没有明确明确地以创建单独的分离/独立进程为目标,例如,通过:

  • 段使用PInvoke。CreateProcess
  • 使用
  • (new System.Management.ManagementClass("Win32_ProcessStartup"))
    .Properties["CreateFlags"].Value = 8;
    
  • 或在应用关闭后通过单独的shell脚本启动子进程或其他在应用关闭后仍在运行的进程来维持子进程的活动;

  • 使用CreateRemoteThread在另一个独立进程中创建新线程
  • 等。

或发现已经独立运行的进程,你不需要也不应该"关闭"或处置由应用进程生成的进程。Windows(操作系统)将关闭任何由应用进程生成的未关闭的进程。

而且,我认为一旦应用程序开始退出或关闭,就不可能在应用程序中执行任何代码。

PS(离题评论):
我甚至没有看到您在代码中关闭(实际上应该杀死)或处置您的进程……