gpt4 book ai didi

c# - 等待 2 个线程中的 1 个完成

转载 作者:行者123 更新时间:2023-11-30 14:46:34 24 4
gpt4 key购买 nike

我的代码中有一个位置,我需要等待传感器识别手指,或者用户按下一个键来中止此操作并返回主菜单。
我尝试将条件变量与 Monitor 和锁定概念一起使用,但是当我尝试提醒主线程时,没有任何反应。

代码:

private static object _syncFinger = new object(); // used for syncing

private static bool AttemptIdentify()
{
// waiting for either the user cancels or a finger is inserted
lock (_syncFinger)
{
Thread tEscape = new Thread(new ThreadStart(HandleIdentifyEscape));
Thread tIdentify = new Thread(new ThreadStart(HandleIdentify));
tEscape.IsBackground = false;
tIdentify.IsBackground = false;
tEscape.Start();
tIdentify.Start();
Monitor.Wait(_syncFinger); // -> Wait part
}

// Checking the change in the locked object

if (_syncFinger is FingerData) // checking for identity found
{
Console.WriteLine("Identity: {0}", ((FingerData)_syncFinger).Guid.ToString());
}
else if(!(_syncFinger is Char)) // char - pressed a key to return
{
return false; // returns with no error
}

return true;
}

private static void HandleIdentifyEscape()
{
do
{
Console.Write("Enter 'c' to cancel: ");
} while (Console.ReadKey().Key != ConsoleKey.C);
_syncFinger = new Char();
LockNotify((object)_syncFinger);
}

private static void HandleIdentify()
{
WinBioIdentity temp = null;
do
{
Console.WriteLine("Enter your finger.");
try // trying to indentify
{
temp = Fingerprint.Identify(); // returns FingerData type
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
// if couldn't identify, temp would stay null
if(temp == null)
{
Console.Write("Invalid, ");
}
} while (temp == null);

_syncFinger = temp;
LockNotify(_syncFinger);
}

private static void LockNotify(object syncObject)
{
lock(syncObject)
{
Monitor.Pulse(syncObject);
}
}

最佳答案

when i try to alert the main thread, nothing happens.

那是因为主线程正在等待这里创建的对象的监视器:

private static object _syncFinger = new object(); // used for syncing

但是您的每个线程都会替换该对象值,然后向监视器发送信号以获取 对象。主线程不知道新对象,因此向监视器发出新对象的信号当然不会对主线程产生影响。

首先,任何时候你为了使用 with lock 而创建一个对象时,将其设为readonly:

private static readonly object _syncFinger = new object(); // used for syncing

这样做总是正确的,这将防止您在线程等待时犯下更改受监视对象的错误。

接下来,创建一个单独的字段来保存 WinBioIdentity 值,例如:

private static WinBioIdentity _syncIdentity;

然后使用 that 将结果中继回主线程:

private static bool AttemptIdentify()
{
// waiting for either the user cancels or a finger is inserted
lock (_syncFinger)
{
_syncIdentity = null;
Thread tEscape = new Thread(new ThreadStart(HandleIdentifyEscape));
Thread tIdentify = new Thread(new ThreadStart(HandleIdentify));
tEscape.IsBackground = false;
tIdentify.IsBackground = false;
tEscape.Start();
tIdentify.Start();
Monitor.Wait(_syncFinger); // -> Wait part
}

// Checking the change in the locked object

if (_syncIdentity != null) // checking for identity found
{
Console.WriteLine("Identity: {0}", ((FingerData)_syncIdentity).Guid.ToString());
return true;
}

return false; // returns with no error
}

private static void HandleIdentifyEscape()
{
do
{
Console.Write("Enter 'c' to cancel: ");
} while (Console.ReadKey().Key != ConsoleKey.C);
LockNotify((object)_syncFinger);
}

private static void HandleIdentify()
{
WinBioIdentity temp = null;
do
{
Console.WriteLine("Enter your finger.");
try // trying to indentify
{
temp = Fingerprint.Identify(); // returns FingerData type
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
// if couldn't identify, temp would stay null
if(temp == null)
{
Console.Write("Invalid, ");
}
} while (temp == null);

__syncIdentity = temp;
LockNotify(_syncFinger);
}

总而言之,您应该更喜欢使用现代的 async/await 习惯用法:

private static bool AttemptIdentify()
{
Task<WinBioIdentity> fingerTask = Task.Run(HandleIdentify);
Task cancelTask = Task.Run(HandleIdentifyEscape);

if (Task.WaitAny(fingerTask, cancelTask) == 0)
{
Console.WriteLine("Identity: {0}", fingerTask.Result.Guid);
return true;
}

return false;
}

private static void HandleIdentifyEscape()
{
do
{
Console.Write("Enter 'c' to cancel: ");
} while (Console.ReadKey().Key != ConsoleKey.C);
}

private static WinBioIdentity HandleIdentify()
{
WinBioIdentity temp = null;
do
{
Console.WriteLine("Enter your finger.");
try // trying to indentify
{
temp = Fingerprint.Identify(); // returns FingerData type
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
// if couldn't identify, temp would stay null
if(temp == null)
{
Console.Write("Invalid, ");
}
} while (temp == null);

return temp;
}

以上是一个最低限度的例子。最好使 AttemptIdentify() 方法 async 本身,然后使用 await Task.WhenAny() 而不是 Task .WaitAny()。最好包含一些中断任务的机制,即一旦一个任务完成,您应该想要中断另一个任务,这样它就不会继续尝试它的工作。

但这些类型的问题并不是 async/await 版本独有的,不需要解决以改进您现在的代码。

关于c# - 等待 2 个线程中的 1 个完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48548272/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com