Reputation: 308
I'm using TLSharp. My goal is to send files to the user. I created ASP.NET Core Web API service and make HTTP request when I need to send file.
It works well with one file but every time when I get 2 or more requests in a short period of time I get an error:
System.InvalidOperationException: invalid checksum! skip.
Controller:
[Route("upload/{driveId}")]
public async Task<ActionResult> Upload(string driveId)
{
var ms = new MemoryStream();
var file = service.Files.Get(driveId);
string filename = file.Execute().Name;
await file.DownloadAsync(ms);
ms.Position = 0;
new FileExtensionContentTypeProvider().TryGetContentType(filename, out var mime);
var stream = new StreamReader(ms, true);
await _client.SendFileToBot(filename, mime, stream, driveId);
return Ok();
}
SendFileToBot method:
public async Task SendFileToBot(string filename, string mime, StreamReader stream)
{
var found = await client.SearchUserAsync("username", 1);
//find user
var userToSend = found.Users
.Where(x => x.GetType() == typeof(TLUser))
.Cast<TLUser>()
.FirstOrDefault(x => x.Id == 1234567);
var fileResult = await client.UploadFile(filename, stream);
var attr = new TLVector<TLAbsDocumentAttribute>()
{
new TLDocumentAttributeFilename { FileName = filename }
};
var bot = new TLInputPeerUser() { UserId = userToSend.Id, AccessHash = userToSend.AccessHash.Value };
await client.SendUploadedDocument(bot, fileResult, "caption", mime, attr);
}
When the requests are sent together (or in short period of time), they're sent in a single packet to Telegram server and this error occurs. I need help with this error. I've tried to use Task.Delay but it doesn't help.
How can I handle requests to avoid this error?
Upvotes: 7
Views: 517
Reputation: 5459
According this issue, you are not first person who received this error.
Seems like there are something request/response validation issues when using multithreading in TLSharp library.
There is one stable workaround for such type of problems.
Actually, they will be asynchronous, but with one-task-at-one-time access
This dirty but workable solution can be achieved by creating task queue:
public class TaskQueue
{
private readonly SemaphoreSlim _semaphoreSlim;
public TaskQueue()
{
_semaphoreSlim = new SemaphoreSlim(1, 1); // Max threads limited to 1.
}
public async Task<T> Enqueue<T>(Func<Task<T>> taskGenerator)
{
await _semaphoreSlim.WaitAsync();
try
{
return await taskGenerator();
}
finally
{
_semaphoreSlim.Release();
}
}
public async Task Enqueue(Func<Task> taskGenerator)
{
await _semaphoreSlim.WaitAsync();
try
{
await taskGenerator();
}
finally
{
_semaphoreSlim.Release();
}
}
}
Now you must register queue as singleton in Startup.cs
file to be sure that your asp.net core application using one task queue instance to perform uploading on telegram servers:
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddSingleton<TaskQueue>();
//...
}
Next, get your task queue instance in your api controller constructor like:
private readonly TaskQueue taskQueue;
public MyController(TaskQueue taskQueue)
{
this.taskQueue = taskQueue
}
Then, just use it in all of your api methods:
// Code from your API method...
await taskQueue.Enqueue(() => client.SendUploadedDocument(bot, fileResult, "caption", mime, attr));
This will make all requests to telegram servers through TLSharp library synchronous and prevent multithreading issues like in a question.
To be honest, it's just a workaround, not solution of this problem. I'm sure that this issue on github about checksum error must be investigated more detailed and fixed if it possible.
Upvotes: 1