How I can start multiple download async in c# - c#

my problem is the following: I just want to run x requests at the same time depending on the user.
Well, it seems to work fine when the MaxConcurrentDownloads variable is equal to 1, but when I increase it, say 10: I have to wait for the 10taches to finish for it to execute so that Console.WriteLine as to write, when it's supposed to run asynchronously, right?
Can you help me? Here is a minimalist version of my "problem" (Also I want to specify that I have no compiler or syntax errors)
main.c
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace test_client
{
class Program
{
private static client cli = new client();
private static readonly string PATH = #Directory.GetCurrentDirectory();
private static int concurrency = 100;
private static async Task<bool> MakeJOB(int pos)
{
return await cli.NewRequest<bool>((HttpClient client)=>
{
try
{
HttpClientHandler handler = null;
if (cli.handler != null)
handler = cli.GethandlerIndexed(pos);
client = new HttpClient(handler);
cli.AssignDefaultHeaders(client);
using (HttpResponseMessage response = client.GetAsync("https://api.my-ip.io/ip.txt").Result)
using (HttpContent content = response.Content)
Console.WriteLine(content.ReadAsStringAsync().Result + " / " + Task.CurrentId);
return true;
}
catch { /* exception .. */ return false; }
});
}
static void Main(string[] args)
{
ServicePointManager.DefaultConnectionLimit = 100;
MainAsync(args).GetAwaiter().GetResult();
Console.ReadLine();
}
static async Task MainAsync(string[] args)
{
cli.SetConcurrentDownloads(concurrency);
var t = new Task[concurrency];
int pos = 0;
for (int i = 0; i < t.Length; i++, pos++)
t[i] = MakeJOB(pos++);
await Task.WhenAll(t);
}
}
}
client.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Http;
using System.Collections.Concurrent;
using System.Threading;
namespace test_client
{
public class client
{
private readonly ConcurrentDictionary<string, HttpClient> Clients;
public SemaphoreSlim Locker;
private CancellationTokenSource TokenSource = new CancellationTokenSource();
public HttpClientHandler[] handler { get; set; }
public string[] address { get; set; }
public string[] port { get; set; }
public string[] username { get; set; }
public string[] password { get; set; }
public int MaxConcurrentDownloads { get; set; }
private void initializeHandler(string address = "", string port = "", string user = "", string pass = "")
{
initializeHandler(new string[] { string.Concat(address, ":", port, ":", user, ":", pass) });
}
private void initializeHandler(string[] proxies_client)
{
if (proxies_client == null || proxies_client.Length == 0)
return;
this.address = new string[proxies_client.Length];
this.port = new string[proxies_client.Length];
this.username = new string[proxies_client.Length];
this.password = new string[proxies_client.Length];
for (int i = 0; i < proxies_client.Length; i++)
{
var split = proxies_client[i].Split(new char[] { ':' });
this.address[i] = split[0] != "" ? split[0] : "";
this.port[i] = split[1] != "" ? split[1] : "";
this.username[i] = split[2] != "" ? split[2] : "";
this.password[i] = split[3] != "" ? split[3] : "";
}
var proxies = new WebProxy[proxies_client.Length];
NetworkCredential[] credential = new NetworkCredential[proxies_client.Length];
for (int i = 0; i < proxies_client.Length; i++)
{
if (this.username[i] != "")
credential[i] = new NetworkCredential(this.username[i], this.password[i]);
else
credential[i] = CredentialCache.DefaultNetworkCredentials;
}
const string protocol = "http://";
for (int i = 0; i < proxies.Length; i++)
{
if (this.address[i] != "")
{
var uri = proxies_client[i].Split(new char[] { ':' });
if (!uri[0].Contains(protocol))
uri[0] = string.Concat(protocol, uri[0]);
proxies[i] = new WebProxy()
{
Address = new Uri(string.Concat(uri[0], ":", uri[1])),
Credentials = credential[i],
};
}
};
this.handler = new HttpClientHandler[proxies.Length];
for (int i = 0; i < proxies.Length; i++)
{
if (proxies[i].Address.AbsoluteUri != "")
this.handler[i] = new HttpClientHandler() { Proxy = proxies[i] };
else
this.handler[i] = new HttpClientHandler();
}
}
public HttpClientHandler GethandlerIndexed(int index)
{
return (this.handler[index % this.handler.Length]);
}
public void SetConcurrentDownloads(int nb = 1)
{
Locker = new SemaphoreSlim(nb, nb);
}
public client(string[] proxies = null)
{
Clients = new ConcurrentDictionary<string, HttpClient>();
if (Locker is null)
Locker = new SemaphoreSlim(1, 1);
if (proxies != null)
initializeHandler(proxies);
}
private async Task<HttpClient> CreateClient(string Name, bool persistent, CancellationToken token)
{
if (Clients.ContainsKey(Name))
return Clients[Name];
HttpClient newClient = new HttpClient();
if (persistent)
{
while (Clients.TryAdd(Name, newClient) is false)
{
token.ThrowIfCancellationRequested();
await Task.Delay(1, token);
}
}
return newClient;
}
public async Task<T> NewRequest<T>(Func<HttpClient, T> Expression, int? MaxTimeout = 2000, string Id = null)
{
await Locker.WaitAsync(MaxTimeout ?? 2000, TokenSource.Token);
bool persistent = true;
if (Id is null)
{
persistent = false;
Id = string.Empty;
}
try
{
HttpClient client = await CreateClient(Id, persistent, TokenSource.Token);
T result = await Task.Run<T>(() => Expression(client), TokenSource.Token);
if (persistent is false)
client?.Dispose();
return result;
}
finally
{
Locker.Release();
}
}
public void AssignDefaultHeaders(HttpClient client)
{
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");
//client.Timeout = TimeSpan.FromSeconds(3);
}
public async Task Cancel(string Name)
{
if (Clients.ContainsKey(Name))
{
CancellationToken token = TokenSource.Token;
HttpClient foundClient;
while (Clients.TryGetValue(Name, out foundClient) is false)
{
token.ThrowIfCancellationRequested();
await Task.Delay(1, token);
}
if (foundClient != null)
{
foundClient?.Dispose();
}
}
}
public void ForceCancelAll()
{
TokenSource?.Cancel();
TokenSource?.Dispose();
TokenSource = new CancellationTokenSource();
foreach (var item in Clients)
{
item.Value?.Dispose();
}
Clients.Clear();
}
}
}

One thing I spotted in a quick skim: Your line in main.cs::Program.MakeJOB:
using (HttpResponseMessage response = client.GetAsync("https://api.my-ip.io/ip.txt").Result)
should instead read
using (HttpResponseMessage response = await client.GetAsync("https://api.my-ip.io/ip.txt"))
This may not be your only issue, but by not awaiting the GetAsync method, you are effectively blocking on the request rather than yielding control back to the caller so that it can, for instance, context switch between tasks or queue up other tasks.
Same goes for
Console.WriteLine(content.ReadAsStringAsync().Result + " / " + Task.CurrentId);
which should be
Console.WriteLine((await content.ReadAsStringAsync()) + " / " + Task.CurrentId);
Although that one is not likely to block for a significant amount of time.

Related

getter setter can't change textBox.Text control value in Winform c#

Why textBox3.text do not shows value _TextBoxRequestMsg. MessageBox opens and shows _TextBoxRequestMsg value OK, console prints too.
public partial class F_Main : Form
{
private string _TextBoxRequestMsg;
public string TextBoxRequestMsg
{
get { return textBox3.Text; }
set
{
_TextBoxRequestMsg = value;
MessageBox.Show(_TextBoxRequestMsg);
Console.WriteLine(_TextBoxRequestMsg);
textBox3.Text = _TextBoxRequestMsg;
}
}
public F_Main()
{
InitializeComponent();
}
}
public class CdataController : ApiController
{
F_Main mainForm = new F_Main();
public async Task<HttpResponseMessage> PostPayloadEventsOp(string SN, string table, string OpStamp)
{
using (var contentStream = await this.Request.Content.ReadAsStreamAsync())
{
contentStream.Seek(0, SeekOrigin.Begin);
using (var sr = new StreamReader(contentStream))
{
string results = sr.ReadToEnd();
mainForm.TextBoxRequestMsg = results;
}
}
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent("OK", System.Text.Encoding.UTF8);
response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromMinutes(2)
};
return response;
}
}
Your question states that your goal is to change textBox.Text control value in Winform and your code indicates that you want to do this by processing an HttpResponseMessage. Consider that the Form that owns the textBox3 control could await the response so that it can meaningfully process its content and assign the value to the text box.
For a minimal example, mock the API request:
public class MockCdataController : ApiController
{
public async Task<HttpResponseMessage> MockPostPayloadEventsOp(string SN, string table, string OpStamp)
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync("https://stackoverflow.com/q/75310027/5438626");
response.Content = new StringContent("OK", System.Text.Encoding.UTF8);
response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromMinutes(2)
};
return response;
}
}
}
The Form that is in possession of textBox3 could invoke something like this:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
buttonPost.Click += onPost;
}
private async void onPost(object? sender, EventArgs e)
{
try
{
UseWaitCursor = true;
buttonPost.BackColor = Color.LightGreen;
var response = await _controller.MockPostPayloadEventsOp("38D6FF5-F89C", "records", "Asgard");
if((response.Headers != null) && (response.Headers.CacheControl != null))
{
textBox3.Text = $"{response.Headers.CacheControl.MaxAge}";
}
}
finally
{
UseWaitCursor = false;
Cursor.Position = new Point(Cursor.Position.X + 1, Cursor.Position.Y);
}
}
MockCdataController _controller = new MockCdataController();
}

C# System.IndexOutOfRangeException: Index was outside the bounds of the array. But when I check it manualy it is within bounds of the array

My problem is probably stupid, but I can't figure out the solution by myself, so I hope someone here can help me.
I am trying to make a dll file for hosting a server on the localhost. I thought I did everything right, but I receive this error:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at minihttpc.Requests.HttpRequest.ParseHeaders(String[] requestLine) in C:\Users\deqnb\OneDrive\minihttpc\minihttpc\Requests\HttpRequest.cs:line 87
at minihttpc.Requests.HttpRequest.ParseRequest(String requestString) in C:\Users\deqnb\OneDrive\minihttpc\minihttpc\Requests\HttpRequest.cs:line 44
at minihttpc.Requests.HttpRequest..ctor(String requestString) in C:\Users\deqnb\OneDrive\minihttpc\minihttpc\Requests\HttpRequest.cs:line 21
at MiniServerHTTP.WebServer.ConnectionHandler.ReadRequest() in C:\Users\deqnb\OneDrive\minihttpc\MiniServerHTTP.WebServer\ConnectionHandler.cs:line 80
at MiniServerHTTP.WebServer.ConnectionHandler.ProcessRequest() in C:\Users\deqnb\OneDrive\minihttpc\MiniServerHTTP.WebServer\ConnectionHandler.cs:line 28
Here is my code - HttpRequest.cs:
using minihttpc.Common.CoreValidator;
using minihttpc.Common.GlobalConstants;
using minihttpc.Headers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace minihttpc.Requests
{
public class HttpRequest:IHttpRequest
{
public HttpRequest(string requestString)
{
CoreValidator.ThrowIfNullOrEmpty(requestString, nameof(requestString));
this.FormData = new Dictionary<string, object>();
this.QueryData = new Dictionary<string, object>();
this.Headers = new HttpHeaderCollection();
this.ParseRequest(requestString);
}
public string Path { get; private set; }
public string Url { get; private set; }
public Dictionary<string,object>FormData { get; }
public Dictionary<string, object> QueryData { get; }
public IHttpHeaderCollection Headers { get; private set; }
public HttpRequestMethod RequestMethod { get; private set; }
public void ParseRequest(string requestString)
{
string[] splitRequestContent = requestString.Split(new[] {
GlobalConstants.HttpNewLine }, StringSplitOptions.None);
string[] requestLine = splitRequestContent[0].Trim().Split(new[]
{ ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (!this.IsValidReqiestLine(requestLine))
{
throw new BadRequestException();
}
this.ParseRequestMethod(requestLine);
this.ParseRequestUrl(requestLine);
this.ParseRequestPath();
this.ParseHeaders(splitRequestContent.Skip(1).ToArray());
//this.ParseRequestQueryParameters();
this.ParseRequestParameters(splitRequestContent[splitRequestContent.Length - 1]);
}
bool IsValidRequestLine(string[] requestLine)
{
if (requestLine.Count() != 3 && requestLine[2] != "HTTP/1.1")
{
return false;
}
else
{
return true;
}
}
void ParseRequestMethod(string[] requestLine)
{
switch (requestLine[0])
{
case "GET": RequestMethod = HttpRequestMethod.Get; break;
case "POST": RequestMethod = HttpRequestMethod.Post; break;
case "PUT": RequestMethod = HttpRequestMethod.Put; break;
case "DELETE": RequestMethod = HttpRequestMethod.Delete; break;
}
}
void ParseRequestUrl(string [] requestLine)
{
this.Url = requestLine[1];
}
void ParseRequestPath()
{
this.Path = this.Url.Split("?").Take(1).First().ToString();
}
void ParseHeaders(string [] requestLine)
{
foreach(var line in requestLine)
{
Console.WriteLine(line); //a lot of info about the req
if (line == GlobalConstants.HttpNewLine) break;
string[] header = line.Split(' ').ToArray();
//Console.WriteLine(header[1]);
Headers.AddHeader(new HttpHeader(header[0],
header[1]));//seems fine //line 87
}
if (Headers.ContainsHeader("host"))
{
throw new BadRequestException();
}
}
void ParseRequestQueryParameters()
{
if (!(this.Url.Split('?').Length > 1)) return;
this.Url.Split('?', '#')[1].Split('&').Select(plainQueryParameter =>
plainQueryParameter.Split());//not finished !!!!
}
void ParseFormDataParameters(string formData)
{
if (!string.IsNullOrEmpty(formData))
{
formData.Split('&').Select(plainQueryParameter =>
plainQueryParameter.Split('=')).ToList().ForEach(queryParameterKeyValue =>
this.FormData.Add(queryParameterKeyValue[0],
queryParameterKeyValue[1]));
}
}
void ParseRequestParameters(string formData)//not being called
{
ParseRequestQueryParameters();
ParseFormDataParameters(formData);
}
}
}
ConnectionHandler.cs:
using minihttpc.Common.CoreValidator;
using minihttpc.Requests;
using MiniServerHTTP.WebServer.Results;
using MiniServerHTTP.WebServer.Routing;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace MiniServerHTTP.WebServer
{
public class ConnectionHandler
{
private readonly Socket client;
private readonly IServerRoutingTable table;
public ConnectionHandler(Socket client, IServerRoutingTable table)
{
CoreValidator.ThrowIfNull(client, nameof(client));
CoreValidator.ThrowIfNull(client, nameof(client));
this.client = client;
this.table = table;
}
public async Task ProcessRequest()
{
try
{
var httpRequest = await this.ReadRequest();
if (httpRequest != null)
{
Console.WriteLine($"Processing: {httpRequest.RequestMethod} {httpRequest.Path}...");
var httpResponse = this.HandleRequest((IHttpRequest)httpRequest);
this.ProcessResponse(httpResponse);
}
}
catch (BadRequestException e)//400
{
this.ProcessResponse(new TextResult(e.ToString(),
HttpResponseStatusCode.BadRequest));
}
catch (Exception e)//500
{
this.ProcessResponse(new TextResult(e.ToString(),
HttpResponseStatusCode.InternalServerError));
}
this.client.Shutdown(SocketShutdown.Both);
}
private async Task ProcessResponse(IHttpResponse httpResponse)
{
byte[] byteSegments = httpResponse.GetBytes();
await this.client.SendAsync(byteSegments, SocketFlags.None);
}
private IHttpResponse HandleRequest(IHttpRequest httpRequest)
{
if(!this.table.Contains(httpRequest.RequestMethod,
httpRequest.Path))
{
return new TextResult($"Route with method {httpRequest.RequestMethod} and path \"{httpRequest.Path}\"not found.",
HttpResponseStatusCode.NotFound);
}
return this.table.Get(httpRequest.RequestMethod,
httpRequest.Path).Invoke(httpRequest);
}
private async Task<HttpRequest> ReadRequest()
{
var result = new StringBuilder();
var data = new ArraySegment<byte>(new byte[1024]);
while (true)
{
int numberOfBytes = await this.client.ReceiveAsync(data.Array, SocketFlags.None);
if (numberOfBytes == 0) break;
var bytesAsString = Encoding.UTF8.GetString(data.Array, 0,
numberOfBytes);
result.Append(bytesAsString);
if (numberOfBytes < 1023) break;
}
if (result.Length == 0)
{
return null;
}
return new HttpRequest(result.ToString());
}
}
}
When I check the parameters manually and variables in minihttpc.Requests.HttpRequest.ParseHeaders(), everything seems fine. I can't get where the problem is.
string[] header = line.Split(' ').ToArray();
Headers.AddHeader(new HttpHeader(header[0], header[1]));
I can pretty much guarantee you're running into a line that doesn't have a space in it. Maybe there's a line that's empty, for example. That wouldn't be obvious from the Console.WriteLine() that you're doing, because empty lines are kind of invisible.

Else is not working in my payment check program C#

There are only 3 situations for result.
1- Paid
2- waiting for payment
3- blocked
(Think like this is a bank program)
So when I run the code, always says true. Never false. I want it work normally. Need help.
[HttpPut(Name = "OdemeYapildiSosyalOdeme")]
public ActionResult<bool> Put(string tckn, int odemeNo)
{
try
{
DbOperations dbOperations = new DbOperations();
var parameters = new List<SqlParameter>();
var param1 = new SqlParameter("TCKN", tckn);
parameters.Add(param1);
var param2 = new SqlParameter("ODEMENO", odemeNo);
parameters.Add(param2);
if (odemeKd == 0)
{
dbOperations.ExecuteNonQuery("ODEME_YAP", parameters);
return Ok(true);
}
else return Ok(false);
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SosyalYardimApi.Operations;
using System.Data.SqlClient;
using System.Data;
namespace SosyalYardimApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class SosyalOdemeController : ControllerBase
{
private int odemeKd;
private object sosyalOdemeleri;
public bool Boolean { get; private set; }
[HttpGet(Name = "SorgulaSosyalOdeme ")]
public ActionResult<List<SosyalOdeme>> Get(string tckn)
{
try
{
//Yapılacak: Tckn 11 karakterli mi kontrolü yapılacak değilse dönüş olacak,
//return Ok("TCKN Hatalı");
if (tckn.Length == 11)
{
List<SosyalOdeme> sosyalOdemeleri = new List<SosyalOdeme>();
DbOperations dbOperations = new DbOperations();
var parameters = new List<SqlParameter>();
var param = new SqlParameter("TCKN", tckn);
parameters.Add(param);
DataTable dtSonuc = dbOperations.GetData("MUSTERI_SELECT", parameters);
for (int i = 0; i < dtSonuc.Rows.Count; i++)
{
SosyalOdeme sosyalOdeme = new SosyalOdeme();
sosyalOdeme.OdemeNo = Convert.ToInt32(dtSonuc.Rows[i]["ODEMENO"]);
sosyalOdeme.Tckn = Convert.ToString(dtSonuc.Rows[i]["TCKIMLIKNO"]);
sosyalOdeme.Adi = dtSonuc.Rows[i]["MUSTERIAD"].ToString();
sosyalOdeme.SoyAdi = dtSonuc.Rows[i]["MUSTERISOYAD"].ToString();
sosyalOdeme.OdemeKd = Convert.ToInt32(dtSonuc.Rows[i]["ODEME_KD"]);
sosyalOdeme.OdenecekTtr = Convert.ToDecimal(dtSonuc.Rows[i]["ODENECEK_TTR"]);
if (dtSonuc.Rows[i]["ODEME_TR"] != DBNull.Value)
sosyalOdeme.OdenecekDt = Convert.ToDateTime(dtSonuc.Rows[i]["ODEME_TR"]);
sosyalOdemeleri.Add(sosyalOdeme);
}
return Ok(sosyalOdemeleri);
}
else return Ok("hatalı tckn girdiniz");
}
catch (Exception)
{
throw;
}
}
[HttpPut(Name = "OdemeYapildiSosyalOdeme")]
public ActionResult<bool> Put(string tckn, int odemeNo)
{
try
{
//Yapılacak: Odeme no ve tckn e ait ödemeyi bul
//Ödemenin durum kontrolü yap =0 ise
//eğer kontrolden başarılı geçmez ise false dön işlemi kes
DbOperations dbOperations = new DbOperations();
var parameters = new List<SqlParameter>();
var param1 = new SqlParameter("TCKN", tckn);
parameters.Add(param1);
var param2 = new SqlParameter("ODEMENO", odemeNo);
parameters.Add(param2);
if (odemeKd == 0)
{
dbOperations.ExecuteNonQuery("ODEME_YAP", parameters);
return Ok(true);
}
else return Ok(false);
}
catch (Exception)
{
throw;
}
}
}
}
So that's the whole code for odemeKd.
We have one more big code but there is no definition in the other one.
So i hope you can find the answer of this code.
Thank you so much.

Deadlock in Xamarin.Forms

I've got a problem with my Xamarin App. The App uses a custom API to my website. I have not much experience in async/await methods.
The following code shows the App.xaml.cs:
public partial class App : Application
{
public static bool IsUserLoggedIn { get; set; }
public static UserModel currentLoggedInUser { get; set; }
public static List<ActionTypeModel> listTypes;
public static List<ActionSubTypeModel> listSubtypes;
public static List<UserModel> listFriends;
public static List<List<ActionModel>> listActiveActions;
public static List<ActionModel> listLastAction;
public App()
{
this.InitializeComponent();
APIHelper.InitializeClient();
StartApp().Wait();
}
private async Task StartApp()
{
//// DEBUG
//MyAccountStorage.Logout();
string username = await MyAccountStorage.GetUsername().ConfigureAwait(false);
string password = await MyAccountStorage.GetPassword().ConfigureAwait(false);
string user_id = await MyAccountStorage.GetId().ConfigureAwait(false);
if (username != null && password != null)
{
currentLoggedInUser = new UserModel();
if (user_id != null)
currentLoggedInUser.user_id = Convert.ToInt32(user_id);
currentLoggedInUser.username = username;
currentLoggedInUser.password = password;
bool isValid = false;
isValid = await AreCredentialsCorrect(0, currentLoggedInUser.username, currentLoggedInUser.password).ConfigureAwait(false);
if (isValid)
{
IsUserLoggedIn = true;
await FillLists().ConfigureAwait(false);
MainPage = new NavigationPage(await MyPage.BuildMyPage().ConfigureAwait(false));
}
else
{
IsUserLoggedIn = false;
MainPage = new NavigationPage(await LoginPage.BuildLoginPage().ConfigureAwait(false));
}
}
else
{
IsUserLoggedIn = false;
MainPage = new NavigationPage(await LoginPage.BuildLoginPage().ConfigureAwait(false));
}
}
private async Task FillLists()
{
listFriends = await DataControl.GetFriends(App.currentLoggedInUser.user_id, App.currentLoggedInUser.username, App.currentLoggedInUser.password).ConfigureAwait(false);
if (listFriends == null)
listFriends = new List<UserModel>();
listTypes = await DataControl.GetTypes(App.currentLoggedInUser.username, App.currentLoggedInUser.password).ConfigureAwait(false);
if (listTypes == null)
listTypes = new List<ActionTypeModel>();
listActiveActions = new List<List<ActionModel>>();
for (int i = 0; i < listTypes.Count; i++)
listActiveActions.Add(await DataControl.GetActiveActions(listTypes[i].action_type_id, currentLoggedInUser.user_id, currentLoggedInUser.username, currentLoggedInUser.password).ConfigureAwait(false));
listSubtypes = await DataControl.GetSubtypes(App.currentLoggedInUser.username, App.currentLoggedInUser.password).ConfigureAwait(false);
if (listSubtypes == null)
listSubtypes = new List<ActionSubTypeModel>();
listLastAction = await DataControl.GetLastAction(App.currentLoggedInUser.user_id, App.currentLoggedInUser.username, App.currentLoggedInUser.password).ConfigureAwait(false);
if (listLastAction == null)
listLastAction = new List<ActionModel>();
}
public static async Task<bool> AreCredentialsCorrect(int type, string user, string pass, string nick = "", string email = "")
{
List<UserModel> listUsers;
if (type == 1)
listUsers = await DataControl.CheckCredentials(1, user, pass, nick, email).ConfigureAwait(false);
else
listUsers = await DataControl.CheckCredentials(0, user, pass).ConfigureAwait(false);
if (listUsers != null)
if (listUsers.Any())
{
currentLoggedInUser = listUsers.First();
currentLoggedInUser.password = pass;
return true;
}
return false;
}
}
I have the API in DataControl.cs:
public static async Task<List<UserModel>> CheckCredentials(int type, string username, string pass, string email = "", string nickname = "")
{
string password = APIHelper.GetHashSha256(pass);
string url = string.Empty;
if (type == 0)
url = APIHelper.ApiClient.BaseAddress + "/account/login.php?username=" + username + "&password=" + password;
if (type == 1)
{
string nick = string.Empty;
if (string.IsNullOrEmpty(nickname) == false)
nick = "&nickname=" + nickname;
url = APIHelper.ApiClient.BaseAddress + "/account/signup.php?username=" + username + "&password=" + password + "&email=" + email + nick;
}
if (string.IsNullOrEmpty(url))
return null;
using (HttpResponseMessage response = await APIHelper.ApiClient.GetAsync(url).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
List<UserModel> listUsers = JsonConvert.DeserializeObject<List<UserModel>>(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
return listUsers;
}
else
return null;
}
}
That's one of the different async methods. When I leave out the ConfigureAwait(false), I run into a deadlock. When I add it to the code I run into an error.
Could you please help me.
As #GSerg already wrote, you have to restructure the code. The App constructor must set the MainPage to some page. That one can be empty saying something like "Loading data".
Then you can start a background Task which retrieves the data you need.
When the data has been loaded, then you can update your page with the newly loaded data. But UI updates always have to happen on the UI thread. This is the same on all platforms. So you have to switch back with Device.BeginInvokeOnMainThread(...).
public App()
{
InitializeComponent();
APIHelper.InitializeClient();
MainPage = new LoadingPage();
// start a background thread
Task.Run(async () =>
{
try
{
await StartApp(); // load the data
// go back to the main thread
Device.BeginInvokeOnMainThread(() =>
{
// replace the MainPage with one which shows the loaded data
MainPage = new DataPage();
});
}
catch (Exception ex)
{
// handle the exception
}
});
}
You can use Task.Run(
//call your async method here
);
So in your case:
Task.Run(Startup);

How to keep data for different guilds/servers for Discord Bots

I am currently undertaking a project in which I am trying to make a RPG for a discord bot. I am currently struggling with how to implement a way to keep data for different servers separate. For example, I'm trying to store the location of the party for each server. I have tried testing moving from 'town' to 'forest'. It works on the server that the command is used, but all other servers that the bot is on also have their location updated to 'forest'. Since I'm new to c# as well I am struggling to work out a way to keep the location being updated on each server.
A possible solution would be to store an object for each guild in an array and reference it whenever guild specific data is required, however this doesn't seem like an elegant solution.
What would be the best way to achieve data separation between guilds?
MAIN
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using TestBot2.Modules;
namespace TestBot2
{
class Program
{
static void Main(string[] args){
new Program().RunBotAsync().GetAwaiter().GetResult();
}
private DiscordSocketClient _client;
private CommandService _command;
private IServiceProvider _service;
public async Task RunBotAsync()
{
_client = new DiscordSocketClient();
_command = new CommandService();
_service = new ServiceCollection()
.AddSingleton(_client)
.AddSingleton(_command)
.BuildServiceProvider();
string botToken = *** BOT TOKEN ***;
//event subscription
_client.Log += Log;
await RegisterCommandAsync();
await _client.LoginAsync(TokenType.Bot, botToken);
await _client.StartAsync();
await Task.Delay(-1);
}
private Task Log(LogMessage arg)
{
Console.WriteLine(arg);
return null;
}
public async Task RegisterCommandAsync()
{
_client.MessageReceived += HandleCommandAsync;
await _command.AddModulesAsync(Assembly.GetEntryAssembly());
}
private async Task HandleCommandAsync(SocketMessage arg)
{
var message = arg as SocketUserMessage;
if (!(message is SocketUserMessage) || message.Author.IsBot) {
return;
}
int argPos = 1;
if (message.HasStringPrefix("cf!", ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos))
{
var context = new SocketCommandContext(_client, message);
var result = await _command.ExecuteAsync(context, argPos+1, _service);
if (!result.IsSuccess)
Console.WriteLine(result.ErrorReason);
}
}
}
}
UTILITY
static string location = "town"; //curent loc
static string[] locations = //array of vlaid loc
{
"town", "forest"
};
int[,] travelMtx = new int[,] //distance matrix
{
{0,2 },
{2,0 }
};
public string D6()
{
Random rnd = new Random();
string reply;
reply = Convert.ToString(rnd.Next(1, 7));
return reply;
}
public string charName(string charowner = "")
{
string charname;
System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection();
conn.ConnectionString = [FILE LOCATION]
conn.Open();
String my_query = "SELECT CharName FROM Chars WHERE CharOwner='" + charowner + "'";
Console.WriteLine(my_query);
OleDbCommand cmd = new OleDbCommand(my_query, conn);
charname = (string)cmd.ExecuteScalar();
Console.Write(charname);
return charname;
}
public string usermention(string user = "")
{
return user;
}
public string getLoc()
{
return Utility.location;
}
public void setLoc(string location)
{
Utility.location = location;
}
public bool checkLoc(string dest)
{
for (int i = 0; i < locations.Length; i++)
{
if (dest.ToLower() == locations[i])
{
return true;
}
}
return false;
}
public int travelTime(string location, string dest)
{
int x = 0;
int y = 0;
for (int i = 0; i < locations.Length; i++)
{
if (location.ToLower() == locations[i])
{
x = i;
}
if (dest.ToLower() == locations[i])
{
y= i;
}
}
return travelMtx[x,y];
}
}
}
TRAVEL
public class Travel : ModuleBase<SocketCommandContext>
{
[Command("Travel")]
public async Task PingAsync(string dest = "")
{
Utility Util = new Utility();
string loc = Util.getLoc();
int travelTime = 0;
if (Util.checkLoc(dest) == true)
{
travelTime = Util.travelTime(loc, dest);
}
Util.setLoc(dest);
await ReplyAsync("you are now in " + dest + " it took " + travelTime + " days" );
}
}
}
I think you could try to store it together with the serverip, so that you can ask for CharOwner='" + charowner + "'" and ServerIp='" + serverip + "'" in you WHERE part of the sql.
It's just a guess, but maybe it works. :)

Categories

Resources