我有一个静态方法,我希望在其中缓存我的WPF应用程序运行所需的所有数据。
public static async Task CacheAllAsync() { ... }
现在,为了缓存数据,我在每个模型中都有专门的缓存方法,我需要缓存数据。像这样:
public static void CacheAuthObjects( IAsyncResult result )
{
SqlCommand cmd = (SqlCommand) result.AsyncState;
SqlDataReader dbr = cmd.EndExecuteReader( result );
try
{
while ( dbr.Read() )
{
CachedData.AuthObjs.Add( new AuthObj( dbr ) );
}
dbr.Close();
}
catch
{
// log; send email to admin...
}
}
我在我的' CacheAllAsync'中使用了这种方法。像这样的方法:
cmd = new SqlCommand( "SELECT ...." );
cmd.Connection = Engine.CreateDefaultDBConnection();
await cmd.Connection.OpenAsync();
cmd.BeginExecuteReader( AuthObjectDB.CacheAuthObjects, cmd );
我在这里的第一个问题是我不知道手术何时完成。我在网上找到了一些关于使用' BeginExecuteReader'的例子,但他们只会说你需要使用' EndExecuteReader',而不是确切地显示如何。
这里的目标是启动多个BeginExecuteReader
(我猜他们大约10或15个)并让他们在完成时告诉我,这样我就可以更新我的GUI最后一个是完整的。所以,请记住,当最后一个专用缓存方法完成时,我需要使用CacheAllAsync
方法返回任务。
P.S。 如果你告诉我这不是一个好的方法我会如何改进它,我也将不胜感激。也许将所有这些10-15个分离的线程只放在一个队列中,然后让它们等待对方?我想,这会更慢,但更安全,CPU消耗更少,所以我更喜欢第一种方法。
答案 0 :(得分:-1)
这只是实现目标的另一种尝试。你对此有何看法?
我把其余的逻辑(连接字符串,命令和打开连接)用于在其专用方法中缓存每个模型列表,如下所示:
public static bool CacheAuthObjects( )
{
SqlCommand cmd = new SqlCommand( "SELECT ..." );
cmd.Connection = Engine.CreateDefaultDBConnection();
cmd.Connection.Open();
SqlDataReader dbr = cmd.ExecuteReader();
try
{
while ( dbr.Read() )
{
CachedData.AuthObjects.Add( new AuthObject( dbr ) );
}
dbr.Close();
}
catch
{
// log, send mail..
return false;
}
finally
{
cmd.Connection.Close();
}
return true;
}
如您所见,我现在使用ExecuteReader
。我正在使用此方法创建Task
,将其放入列表中,启动所有任务并等待它们,所有这些都在主缓存方法中,如下所示:
public static async Task<bool> CacheAllAsync()
{
// creating the list for the tasks
List<Task<bool>> cachingTasks = new List<Task<bool>>();
// adding the task
cachingTasks.Add( new Task<bool>(AuthObjectDB.CacheAuthObjects ) );
// ... adding the rest of the tasks....
// starting the tasks
foreach ( Task t in cachingTasks )
t.Start();
// awaiting the tasks to complete
Task<bool[]> task = Task.WhenAll( cachingTasks );
await task;
// checking if any of the tasks failed to complete
foreach ( bool b in task.Result )
if ( !b ) return false;
return true;
}
伊万,你的意思是这样的吗?我更喜欢这个,因为逻辑更均匀地传播。我想如果我要读取主要缓存方法中的数据,你建议ExecuteReader
。或者我做错了什么?代码实际上运行良好,UI响应并且正在加载数据。