我们正在使用Xamarin用SQLite为Android和ios编写C#代码.但是关于如何使用sqlite,我似乎有一个概念上的误解:
根据stackoverflow的回答,它说 - 一个帮助器和一个数据库连接.在它周围使用锁定以确保任何时候只有一个线程正在访问sqlite db.
我的问题是 - 如果是这样的话 - 异步的用途是什么?
我试图使用同步代码的异步 - 代码给了我正确的编译错误,以避免死锁.
为什么我不能在lock语句的主体中使用'await'运算符?
public async Task InsertAsync<T> (T item){
lock (mutex) {
await asyncConnection.InsertAsync (item);
}
}
public async Task InsertOrUpdateAsync<T> (T item){
lock (mutex) {
int count = await asyncConnection.UpdateAsync (item);
if (0 == count) {
await asyncConnection.InsertAsync (item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
失败.但是 - 如果我要使用锁来确保我一次使用一个连接一个线程作为sqlite中的最佳实践 - 为什么有一个异步sqlite库呢?
为什么有些线程会在网络上推广异步sqlite用法.
在android和iphone中sqlite真正的最佳实践是什么?只是使用同步版本?
我有一个 Web API 服务,它将接受不同客户端访问两个 SQL Server 数据库的许多并发请求,所有控制器(大约 65 个)都有一个 BaseApiController,请在下面找到常用方法。
protected async Task<IEnumerable<TObject>> GetSyncData<TObject>(
Guid clientId,
string clientSyncTable,
Func<Task<IEnumerable<TObject>>> initialDataFunc,
Func<ISyncMetadataClient, Task<IEnumerable<TObject>>> sinceLastSyncDataFunc,
Func<ISyncMetadataClient, Task<bool>> insertClientSyncMetadata,
Func<IEnumerable<ISyncObject>, IEnumerable<TSyncMetadata>> getSyncMetadataFromSyncObjects,
Func<IEnumerable<TObject>, Task<IEnumerable<TObject>>> getExistingObjectsWithSyncMetadata) where TObject : ISyncObject
{
// Get the client sync metadata.
ISyncMetadataClient syncMetadataClient =
await SyncDataService.ClientSyncMetadata.GetFirstAsync(new { ClientId = clientId, SyncTable = clientSyncTable })
.ConfigureAwait(false);
// No metadata for this client and this resource. Use a lock or a better thread safe practice?
if (syncMetadataClient == null)
{ …Run Code Online (Sandbox Code Playgroud) 正如Stephen Cleary著名的博客文章所指出的那样,永远不要尝试同步运行异步代码(例如,通过Task.RunSynchronously()或访问Task.Result)。另一方面,您不能在lock语句中使用async / await 。
我的用例是ASP.NET Core应用程序,它使用IMemoryCache缓存一些数据。现在,当数据不可用时(例如,删除了缓存),我必须重新填充它,并且应该使用来保护lock。
public TItem Get<TItem>(object key, Func<TItem> factory)
{
if (!_memoryCache.TryGetValue(key, out TItem value))
{
lock (_locker)
{
if (!_memoryCache.TryGetValue(key, out value))
{
value = factory();
Set(key, value);
}
}
}
return value;
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,工厂功能不能异步!如果必须异步该怎么办?
附言:此答案下方评分最高(超过70票)的评论要求相同,但完全没有答复。
编辑:我认为这不是一个重复的问题,从某种意义上说,链接的答案是作者的第三方库。没有第三方代码,没有解决方案吗?也许提到SemaphoreSlim.WaitAsync可以成功使用吗?..它们各自的优缺点是什么?我们可以讨论一下吗?请重新打开问题。我不认为该问题可以通过链接的答案来解决(它只是提出了非常有主见的,主观的“ hack”)。
我有几种方法可以向数据库报告一些数据。我们希望异步调用对数据服务的所有调用。这些对数据服务的调用都结束了,因此我们要确保这些 DS 调用在任何给定时间按顺序依次执行。最初,我在这些方法中的每一个上使用 async await 并且每个调用都是异步执行的,但我们发现如果它们乱序,那么就有出错的空间。
所以,我认为我们应该将所有这些异步任务排队并在一个单独的线程中发送它们,但我想知道我们有哪些选择?我遇到了 'SemaphoreSlim' 。这在我的用例中是否合适?或者还有哪些其他选项适合我的用例?请指导我。
所以,我目前在我的代码中有什么
public static SemaphoreSlim mutex = new SemaphoreSlim(1);
//first DS call
public async Task SendModuleDataToDSAsync(Module parameters)
{
var tasks1 = new List<Task>();
var tasks2 = new List<Task>();
//await mutex.WaitAsync(); **//is this correct way to use SemaphoreSlim ?**
foreach (var setting in Module.param)
{
Task job1 = SaveModule(setting);
tasks1.Add(job1);
Task job2= SaveModule(GetAdvancedData(setting));
tasks2.Add(job2);
}
await Task.WhenAll(tasks1);
await Task.WhenAll(tasks2);
//mutex.Release(); // **is this correct?**
}
private async Task SaveModule(Module setting)
{
await Task.Run(() …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
public const int ThreadLimitMax = 128;
private static object setThreadLimitLock = new object();
private static SemaphoreSlim totalThreadLimiter = new SemaphoreSlim(ThreadLimit, ThreadLimitMax);
public static int ThreadLimit { get; private set; } = 128;
public static async Task SetThreadLimit(int max)
{
if (max > ThreadLimitMax)
throw new ArgumentOutOfRangeException(nameof(max), $"Cannot have more than {ThreadLimitMax} threads.");
if (max < 1)
throw new ArgumentOutOfRangeException(nameof(max), $"Cannot have less than 1 threads.");
lock (setThreadLimitLock)
{
int difference = Math.Abs(ThreadLimit - max);
if (max < ThreadLimit)
{ …Run Code Online (Sandbox Code Playgroud) c# ×5
async-await ×2
asynchronous ×2
locking ×2
semaphore ×2
.net ×1
asp.net ×1
queue ×1
sqlite ×1