线程竞争和锁定关键字
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程竞争和锁定关键字相关的知识,希望对你有一定的参考价值。
我的应用程序有一个登录区域,使用线程访问数据库,不冻结UI。
在登录期间,系统进行一些操作以打开主窗口,并在另一个线程中加载用户数据(和权限)。
但有时,当数据库挂起时,系统会在加载用户之前完成加载。
系统执行的最后一个操作是应用权限(在线程中加载用户的数据)。
我还有一个静态User
对象,它包含进行登录的用户数据,如其权限等。
当应用程序在加载用户之前从静态用户对象获取数据时,会发生此问题。权限为空并且未正确应用,从而导致意外行为。
如何确保加载静态用户,并且只在网络/数据库延迟的极端情况下冻结UI?
我尝试使用lock
,但它根本不起作用。
这是我的代码:
int id = User.GetId(user, password); // returns 0 if the user does not exists
if (id != 0)
{
new Thread(() =>
{
lock (User.CurrentUser) // Try to lock the static CurrentUser object
{
User.LoadCurrentUser(id); // Loads the CurrentUser object
}
}).Start();
InitializeSystem(); //Make some work on the system. After that, this
//will get the User.CurrentUser object to apply the
//user's permissions.
}
方法User.LoadCurrentUser(id);
填充用户。
我知道锁无法正常工作,因为我在锁中放了一个Thread.Sleep(5000);
,并且系统在2秒内以错误的权限启动。
不考虑删除线程,因为它会破坏我的UI。
编辑
我需要使用.Net Framework 4.0来确保Windows XP的兼容性。
答案
这是await
或链式任务的完美候选者。
等待版本:
async void YourLoginButtonEventHandler() {
int id = User.GetId(user, password); // returns 0 if the user does not exists
if (id != 0) {
await Task.Run(() => User.LoadCurrentUser(id)); // Loads the CurrentUser object
InitializeSystem();
}
}
或者你可以链接它们:
if (id != 0) {
Task.Run(() => User.LoadCurrentUser(id))
.ContinueWith(t => InitializeSystem(), TaskScheduler.FromCurrentSynchronizationContext);
}
注意:可能是一些语法错误..我直接在这里打字。
我基本上想要告诉你的是......你正在努力解决这个问题。对于这种事情有更新的构造..学习它们:)
另一答案
您可以使用Thread.Join来阻止主线程,直到另一个线程完成或超时。
int id = User.GetId(user, password); // returns 0 if the user does not exists
if (id != 0)
{
var newThread = new Thread(() =>
{
lock (User.CurrentUser) // Try to lock the static CurrentUser object
{
User.LoadCurrentUser(id); // Loads the CurrentUser object
}
}).Start();
InitializeSystem();
if (newThread.Join(someTimeOut))
// use the User.CurrentUser object to apply the user's permissions.
else
// thread timed out, waiting for user load takes too long...
}
以上是关于线程竞争和锁定关键字的主要内容,如果未能解决你的问题,请参考以下文章
#yyds干货盘点# Java | 关于synchronized相关理解