当我试图提醒主线程时,什么都没有发生。
这是因为主线程正在监视器上等待在此处创建的对象:
private static object _syncFinger = new object(); // used for syncing
但每个线程都会替换该对象值,然后向监视器发出信号
新
对象主线程不知道新对象,因此当然,向监视器发送新对象的信号对主线程没有影响。
首先,无论何时创建对象以用于
lock
,成功
readonly
:
private static readonly object _syncFinger = new object(); // used for syncing
这始终是正确的做法,这将防止您在线程等待被监视对象时犯更改被监视对象的错误。
接下来,创建一个单独的字段来保存
WinBioIdentity
值,例如:
private static WinBioIdentity _syncIdentity;
和使用
那个
要将结果传回主线程,请执行以下操作:
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()
方法
异步
本身,然后使用
await Task.WhenAny()
而不是
Task.WaitAny()
. 最好包括一些中断任务的机制,也就是说,一旦一个任务完成,你应该想中断另一个任务,这样它就不会到处乱跑,继续尝试它的工作。
但这些问题并不是
异步
/
等候
版本,无需解决即可改进现有代码。