Populate a ComboBox on MainForm via Logic.cs - c#

I was able to populate a comboBox via StreamReader on the MainForm. I find now that I will need that same information in several different comboBox's on different dialog's. This works accept that I can't seem to be able to get at the comboBox "cbTask". Error states "The name 'cbTask' does not exist in the current context". The code
public static void TaskPopulate()
{
try
{
StreamReader task = new StreamReader(dataFolder + TasksFile);
string tasks = task.ReadLine();
while (tasks != null)
{
cbTask.Items.Add(tasks);
tasks = task.ReadLine();
}
}
catch
{
}
}
dataFolder is the path and TasksFile is the file name. Works good if I leave it on the MainForm.
Can anyone point me in the right direction?? Thanks for viewing in advance!! I appreciate it. Have a Great Day!!
EDIT: After reading over this a few times it looks like my question is not clear. I'm trying to add information from the StreamReader to multiple comboBoxes on multiple child dialogs.

My first answer provided an Enterprise-style solution, so here is another approach if you wanted a simpler and less expansive way to handle your challenge.
public static class MyTaskComboBoxPopulater()
{
public static void LoadTasksToCombobox(ComboBox comboBox)
{
try
{
StreamReader task = new StreamReader(dataFolder + TasksFile);
string tasks = task.ReadLine();
while (tasks != null)
{
comboBox.Items.Add(tasks);
tasks = task.ReadLine();
}
}
catch
{
}
}
}
public Form MainForm()
{
public static void TaskPopulate()
{
MyTaskComboBoxPopulater.LoadTasksToCombobox(cbTask);
}
}

Move it to a new Service, and depend on the Service reference for whichever Form you need.
Sample code:
public class MyService()
{
public IEnumerable<string> LoadTasks()
{
var taskList = new List<string>();
try
{
StreamReader task = new StreamReader(dataFolder + TasksFile);
string tasks = task.ReadLine();
while (tasks != null)
{
taskList.Add(tasks);
tasks = task.ReadLine();
}
}
catch
{
}
return taskList;
}
}
public Form MainForm()
{
private MyService _myService = new MyService();
public static void TaskPopulate()
{
foreach(var task in _myService.LoadTasks())
{
cbTask.Items.Add(task);
}
}
}

Do you have that method in the main window or in a seperate class? If it is in a seperate class, that might explain why "cbTask" Cannot be found.
Also, try using something similar to this string variable = otherForm.TextBox1.Text;

Related

How to erase all Xamarin.Forms.Application.Current.Properties?

I'm creating a Helper to find out if the user is using my app for the first time (not only), that's why I'm using Xamarin.Forms.Aplication.Current.Properties. When the user logs out, the app will remove all keys, include that. But this is not happening and I don't know what.
My code:
public static class FirstUseAppHelper
{
public static string FIRST_USE = "FirstUse";
public static void Initialize()
{
if (Application.Current.Properties.ContainsKey(FIRST_USE))
{
Application.Current.Properties[FIRST_USE] = false;
}
else
{
Application.Current.Properties[FIRST_USE] = true;
}
}
public static bool CheckFirstUseApp()
{
if (!Application.Current.Properties.ContainsKey(FIRST_USE))
throw new Exception("Key not found.");
else
return Application.Current.Properties[FIRST_USE].Equals(true);
}
}
When the app starts (App.Xaml.cs) is called the method:
protected override async void OnInitialized()
{
InitializeComponent();
FirstUseAppHelper.Initialize();
...
}
Logout method (This is not working):
LogOutCommand = new DelegateCommand(() =>
{
var keys = Application.Current.Properties.Keys.ToList();
foreach (var k in keys)
Application.Current.Properties[k] = null;
Application.Current.SavePropertiesAsync();
}
I understand that the code is correct, but for some reason the keys are not being erased. Has anyone had this problem or has a better solution?
This is because the automatic backup of the latest versions of Android.
You need to add android:allowBackup="false" and android:fullBackupContent="false" to the tag in AndroidManifest.xml
if you don't want to back up your data or if you want to include or exclude some features.

How to check if IDataReader is closed by using the .net compiler API

I am trying to write a code analyzer that will check if there are any IDataReaders that are not closed.
I have gone through this question but it does not explain how it can be done, I have also tried to read through the documentation in the github link The English language used here is too complicated and I did not understand how I will be able to find all instances of type IDataReader and verify that the method close() is being called on it before any variable of the said type goes out of scope.
I have tried creating a project of type Analyzer with code fix in visual studio, I tried to register the operation context in the Initialize method of my class (Which is extended from the type DiagnosticAnalyzer as follows:
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class DataReaderAnalyzerAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "DataReaderAnalyzer";
private static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.AnalyzerTitle), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.AnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.AnalyzerDescription), Resources.ResourceManager, typeof(Resources));
private const string Category = "DBConnectionCheck";
private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Error, isEnabledByDefault: true, description: Description);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }
public override void Initialize(AnalysisContext context)
{
context.RegisterOperationAction((operationContext) =>
{
((Microsoft.CodeAnalysis.CSharp.Syntax.AssignmentExpressionSyntax)((Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax)operationContext.Operation.Syntax).Expression).Left
}
, OperationKind.ExpressionStatement);
}
}
I want to find all the references of the occurrence of the variable that holds the type IDataReader, make sure that the close method is being called in this variable before it is lost out of scope.
A sample of my code that I would like to analyze is as follows.
class Program
{
static void Main(string[] args)
{
IDataReader reader = null;
try
{
Database db = DatabaseFactory.CreateDatabase("ApplicationConnection");
reader = GetDataReader(db);
while (reader.Read())
{
//Do somethig with the data here
}
reader.Close();
}
catch (Exception)
{
throw;
}
finally
{
if (reader != null && !reader.IsClosed)
{
reader.Close();
}
}
}
public static IDataReader GetDataReader(Database db)
{
DbCommand dbcmd = db.GetSqlStringCommand("some select statement to get data from oracle data base");
var reader = db.ExecuteReader(dbcmd);
return reader;
}
}
Ultimately, the code shown isn't great, and IMO it would be the wrong solution to write an analyzer to enforce it.
There is a very simple way of doing this style of operation, and it mostly involves forgetting about Close, and using the fact that it is IDisposable - which is the intended API for this kind of scenario. Then it becomes much, much simpler - so much simpler that a: you don't need a special analyzer for it, and b: existing analyzers that work against IDisposable probably do the job for you.
using var reader = GetDataReader(db);
while (reader.Read())
{
//Do somethig with the data here
}
with no try/catch/finally etc; the compiler will add everything you need for this to do the right thing, simply via the using. Note that with older compilers, this needs to be:
using (var reader = GetDataReader(db))
{
while (reader.Read())
{
//Do somethig with the data here
}
}
As a side note: I would strongly suggest not fighting the ADO.NET API - it isn't a useful way of spending your time; tools like Dapper do most common things for you, so you don't need to write this code - and it knows all the corner cases to avoid.
A typical Dapper usage might be:
string region = ...
var users = connection.Query<User>(
"some * from Users where Region = #region",
new { region } // parameters
).AsList();
with the library dealing with all the ADO.NET details internally.
The below code is a non battle hardened approach you can follow.
analysisContext.RegisterCompilationStartAction(compilationContext =>
{
var variables = new HashSet<string>();
var tree = compilationContext.Compilation.SyntaxTrees.First();
//iterate over all childnodes starting from root
foreach (var node in tree.GetRoot().ChildNodes())
{
var flat = Flatten(node).ToList();
//find all variable declarations
var varDecls = flat.OfType<VariableDeclarationSyntax>();
foreach (var decl in varDecls)
{
if (!(decl.Type is IdentifierNameSyntax id)) continue;
if (!id.Identifier.Text.Equals("IDataReader")) continue;
//if you are declaring an IDataReader, go store the var name in set
foreach (var reader in decl.Variables)
{
variables.Add(reader.Identifier.Text);
}
}
//find all method calls i.e. reader.Read() etc
var invokes = flat.OfType<InvocationExpressionSyntax>();
foreach (var invoke in invokes)
{
var memberAccess = invoke.Expression as MemberAccessExpressionSyntax;
var ident = memberAccess.Expression as IdentifierNameSyntax;
if(!variables.Contains(ident.Identifier.Text)) continue;
var name = memberAccess.Name as IdentifierNameSyntax;
//if we find any Close() method on reader, remove from var set
if (name.Identifier.Text.Equals("Close"))
{
variables.Remove(ident.Identifier.Text);
}
}
}
// if we have any variables left in set it means Close() was never called
if (variables.Count != 0)
{
//this is where you can report
//var diagnostic = Diagnostic.Create(Rule, location, value);
//context.ReportDiagnostic(diagnostic);
}
});
public static IEnumerable<SyntaxNode> Flatten(SyntaxNode node)
{
yield return node;
var childNodes = node.ChildNodes();
foreach (var child in childNodes)
foreach (var descendant in Flatten(child))
yield return descendant;
}

Multiple tasks returns incorrect result

What I need to do
I need to start different instances of a class in a synchronous context using an async method.
Application structure
In my console application I've declared a List<Bot> class:
private List<Bot> _bots = new List<Bot>(new Bot[10]);
the class Bot contains some methods that takes data from internet, so these methods need to be waited. The method structure looks like this:
public class Bot
{
Competition Comp { get; set; }
public async Task StartAsync(int instance)
{
string url = "";
//based on the instance I take the data from different source.
switch(instance)
{
case 0:
url = "www.google.com";
break;
case 1:
url = "www.bing.com";
break;
}
//Comp property contains different groups.
Comp.Groups = await GetCompetitionAsync(Comp, url);
if(Comp.Groups.Count > 0)
{
foreach(var gp in group)
{
//add data inside database.
}
}
}
}
the Competition class have the following design:
public class Competition
{
public string Name { get; set; }
public List<string> Groups { get; set; }
}
I start all the instances of Bot class using the following code:
for(int i = 0; i < _bots.Count - 1; i++)
{
_bots[i].StartAsync(i);
}
this code will call different times StartAsync of Bot class, in this way, I can manage each instance of the bot, and I can eventually stop or start a specific instance in a separate method.
The problem
The method GetCompetitionAsync create a List<string>:
public async Task<List<string>> GetCompetitionAsync(Competition comp, string url)
{
if(comp == null)
comp = new Competition();
List<string> groups = new List<string();
using (var httpResonse = await httpClient.GetAsync(url))
{
string content = await httpResponse.Content.ReadAsStringAsync();
//fill list groups
}
return groups;
}
essentially this method will fill the List<string> available in Comp. Now, if I execute a single instance of StartAsync all works well, but when I run multiple instances (as the for above), the Comp object (which contains the Competition) have all the properties NULL.
So seems that when I have multiple Task running the synchronous context doesn't wait the async context, which in this case fill the List<string>.
When the code reach this line: if(Competition.Groups.Count > 0) I get a NULL exception, because Groups is null, and other Comp properties are NULL.
How can I manage this situation?
UPDATE
After other attempts, I though to create a List<Task> instead of a List<Bot>:
List<Task> tasks = new List<Task>(new Task[10]);
then instead of:
for(int i = 0; i < _bots.Count - 1; i++)
{
_bots[i].StartAsync(i);
}
I did:
for (int i = 0; i < tasks.Count - 1; i++)
{
Console.WriteLine("Starting " + i);
if (tasks[i] == null)
tasks[i] = new Task(async () => await new Bot().StartAsync(i));
apparently all is working well, I got no errors. The problem is: why? I though to something like a deadlock, that I can't even solve using ConfigureAwait(false);.
The last solution also doesn't allow me to access to Bot method because is now a Task.
UPDATE 2
Okay maybe I gotcha the issue. Essentially the await inside the asynchronous method StartAsync is trying to comeback on the main thread, meanwhile the main thread is busy waiting the task to complete, and this will create a deadlock.
That's why moving the StartAsync() inside a List<Task> has worked, 'cause now the async call is now running on a thread pool thread, it doesn't try to comeback to the main thread, and everything seems to works. But I can't use this solution for the reasons explained above.
I'm prefer use Threads instead of Tasks. IMHO, Threads more simple for understanding.
Note: seems that property Bot.Comp in your code is NOT initialized! I fix this issue.
My version of your code:
public class Bot
{
Competition Comp { get; set; }
System.Thread _thread;
private int _instance;
public Bot()
{
Comp = new Competition ();
}
public void Start(int instance)
{
_instance = instance;
_thread = new Thread(StartAsync);
_thread.Start();
}
private void StartAsync()
{
string url = "";
//based on the instance I take the data from different source.
switch(_instance)
{
case 0:
url = "www.google.com";
break;
case 1:
url = "www.bing.com";
break;
}
//Comp property contains different groups.
GetCompetitionAsync(Comp, url);
if(Comp.Groups.Count > 0)
{
foreach(var gp in group)
{
//add data inside database.
}
}
}
public List<string> GetCompetitionAsync(Competition comp, string url)
{
if(comp.groups == null) comp.groups = new List<string>();
using (var httpResonse = httpClient.GetAsync(url))
{
string content = await httpResponse.Content.ReadAsStringAsync();
//fill list groups
}
return groups;
}
}
Then we run threads:
for(int i = 0; i < _bots.Count - 1; i++)
{
_bots[i].Start(i);
}
Each instance of Bot starts method private void StartAsync() in it's own thread.
Note a implementation of method Bot.Start():
public void Start(int instance)
{
_instance = instance;
_thread = new Thread(StartAsync); //At this line: set method Bot.StartAsync as entry point for new thread.
_thread.Start();//At this line: call of _thread.Start() starts new thread and returns **immediately**.
}
This sort of thing is far simpler if you think in terms of lists and "pure" functions-- functions that accept input and return output. Don't pass in something for them to fill or mutate.
For example, this function accepts a string and returns the groups:
List<string> ExtractGroups(string content)
{
var list = new List<string>();
//Populate list
return list;
}
This function accepts a URL and returns its groups.
async Task<List<string>> GetCompetitionAsync(string url)
{
using (var httpResponse = await httpClient.GetAsync(url))
{
string content = await httpResponse.Content.ReadAsStringAsync();
return ExtractGroups(content);
}
}
And this function accepts a list of URLs and returns all of the groups as one list.
async Task<List<string>> GetAllGroups(string[] urls)
{
var tasks = urls.Select( u => GetCompetitionAsync(u) );
await Task.WhenAll(tasks);
return tasks.SelectMany( t => t.Result );
}
You can then stuff the data into the database as you had planned.
var groups = GetAllGroups( new string[] { "www.google.com", "www.bing.com" } );
foreach(var gp in groups)
{
//add data inside database.
}
See how much simpler it is when you break it down this way?

C# Command parser

im currently expanding my knowledge a little, and wanted to Create a little game for myself.
The Structure is as Following:
Programm.cs creates an instance of Gamecontroller. This Gamecontroller is the lowest level i want to Access. It will create instaces of the Views, and from classes like config.
I want to implement an debug Console with Command Input. These Commands should always start at the Gamecontroller level, and should be able to interact with kinda everything i could do with C# code.
So i want to access the Objects, Member and methods withing Gamecontroller, or Within any nested object.
Currently i cant get to the Properties of an Child, because _member returns an "Type" which gets parsed to RuntimeProperty instead of the Class
Example on Parsing:
"objPlayer.name" > "GameController.objPlayer.name"
"objConfig.someSetting = 10" > "GameController.objConfig.someSetting=10"
"objConfig.functionCall()" > "GameController.objConfig.functionCall()"
"objConfig.objPlayer.setName("someName")" > "GameController.objConfig.objPlayer.setName("someName")"
"objPlayer.name" > "GameController.objPlayer.name"
this is what i got so far:
private void parseComamnd(string Command)
{
var actions = Command.Split('.');
var start = this.GetType();
var last = actions[actions.Length - 1];
foreach (var action in actions)
{
if (action.Contains("(") && action.Contains(")"))
{
_exec(start, action);
}
else
{
start = _member(start, action);
}
}
}
private Type _member(Type pHandle, string pStrMember)
{
return pHandle.GetProperty(pStrMember).GetType();
}
private void _exec(Type pHandle, string pStrFunction)
{
var Regex = new Regex(#"\(|,|\)");
var FunctionParams = Regex.Split(pStrFunction);
var FunctionName = FunctionParams[0];
FunctionParams[0] = "";
FunctionParams = FunctionParams.Where(val => val != "").ToArray();
pHandle.GetMethod(FunctionName).Invoke(FunctionName, FunctionParams);
}
If I understood right, you want to match some string commands with actions you want to perform. In this case you could use Dictionary as a storage for string-delgate couples to match your string commands to actions you want to perform. As an advantage of this approach, you can change matched couples during program runtime as you wish
class SomeClass
{
delegate void OperationDelegate(string value);
IDictionary<string, OperationDelegate> Operations = new Dictionary<string, OperationDelegate>();
public SomeClass()
{
Operations.Add("objPlayer.name", SetName);
Operations.Add("objConfig.someSetting", SetSetting);
}
public void HandleNewValue(string command, string value)
{
try
{
if (Operations.ContainsKey(command))
Operations[command](value);
}
catch (Exception e)
{
Logger.Error(e);
}
}
private void SetName(string value)
{
// Some logic there
}
private void SetSetting(string value)
{
// Some logic there
}
}

Threads conflict in some cases, in loop conditions

I am working on a project that uses Threads. In some cases, I have these problems:
Here is some piece of my code :
List<EmailAddress> lstEmailAddress = new List<EmailAddress>();
private void TimerCheckInternetConnection_Tick(object sender, EventArgs e)
{
lock (TicketLock)
{
if (UtilityManager.CheckForInternetConnection())
{
if (ApplicationRunStatus == Enum_ApplicationRunStatus.UnknownDisconnect || ApplicationRunStatus == Enum_ApplicationRunStatus.IsReady)
{
// Connect
ThreadPool.QueueUserWorkItem((o) =>
{
for (int i = 0; i < lstEmailAddress.Count; i++)
{
lstEmailAddress[i].IsActive = lstEmailAddress[i].Login();
}
this.BeginInvoke(new Action(() =>
{
// some code
}));
});
}
}
}
}
and this is EmailAddress class :
class EmailAddress
{
private Imap4Client imap = new Imap4Client();
private object objectLock = new object();
public bool IsActive;
public string Address;
public string Password;
public string RecieveServerAddress;
public int RecieveServerPort;
public bool Login()
{
lock (objectLock)
{
try
{
imap.ConnectSsl(RecieveServerAddress, RecieveServerPort);
}
catch (Exception)
{
}
try
{
imap.Login(Address, Password);
return true;
}
catch (Exception)
{
return false;
}
}
}
}
And my problem is this:
When I want to use Login procedure that belongs to EmailAddress Class, it has some conflict. As you can see, I used Lock but any thing changed.
For more details:
If I have 3 items in lstEmailAddress , the Login procedure has to be called 3 times by this code. but every time, the login procedure will work on same username and password. So all my emails cannot login correctly.
If I remove threadpool, it will be ok.
Your code is very confusing:
If you add the lock in your code, it will run synchroniously, only one thread at the time, which will lead to performance loss.
If you queue work via QueueUserWorkItem - it will run in other thread, and not inside TicketLock
You should incapsulate locks inside your class, and should not lock entire logic in your program.
You start work for a loop variable i, which is being closured for it's last value, which lead for a problem you state in last sentence.
lock object in Email class isn't static so it's being created for each instance, and doesn't actually lock anithing.
As you are using Invoke method, your code is being started from UI, and you need to pass the synchronization context. I suggest you to use TPL code for this, and do not directly work with ThreadPool
So I suggest you this solution:
List<EmailAddress> lstEmailAddress = new List<EmailAddress>();
private void TimerCheckInternetConnection_Tick(object sender, EventArgs e)
{
// remove this lock as we have another in Email class
//lock (TicketLock)
if (UtilityManager.CheckForInternetConnection())
{
if (ApplicationRunStatus == Enum_ApplicationRunStatus.UnknownDisconnect
|| ApplicationRunStatus == Enum_ApplicationRunStatus.IsReady)
{
for (int i = 0; i < lstEmailAddress.Count; i++)
{
// use local variable to store index
int localIndex = i;
// Connect
ThreadPool.QueueUserWorkItem((o) =>
{
// if you add a lock here, this will run synchroniosly,
// and you aren't really need the ThreadPool
//lock (TicketLock)
lstEmailAddress[localIndex].IsActive = lstEmailAddress[localIndex].Login();
this.BeginInvoke(new Action(() =>
{
// some code
}));
});
}
}
}
}
class EmailAddress
{
// if you have to login only for one user simultaneosly
// use static variables here, other wise simply remove the lock as it is useless
private static Imap4Client imap;
private static object objectLock;
// static constructor for only one initialization for a static fields
static EmailAddress()
{
objectLock = new object();
imap = new Imap4Client();
}
public bool IsActive;
public string Address;
public string Password;
public string RecieveServerAddress;
public int RecieveServerPort;
public bool Login()
{
// aquire a static lock
lock (objectLock)
{
try
{
imap.ConnectSsl(RecieveServerAddress, RecieveServerPort);
}
catch (Exception)
{
// STORE THE EXCEPTION!!!
// return as you haven't connected
return false;
}
try
{
imap.Login(Address, Password);
return true;
}
catch (Exception)
{
// STORE THE EXCEPTION!!!
return false;
}
}
}
}
Change your Code as and try . you code is queing item from lstEmailAddress where it will always go and hit last item from the list. change your code to inquie each item in threadpool. that should fix. it.
for (int i = 0; i < lstEmailAddress.Count; i++)
{
ThreadPool.QueueUserWorkItem((o) =>
{
lstEmailAddress[i].IsActive = lstEmailAddress[i].Login();
}
}

Categories