Get/Set Data to UI-Objects from BackgroundWorker-Thread - c#

latly i've been struggeling with getting and setting data from/to UI-Objects.
I know it's possible to do this from a BackgroundWorker-Thread, by using Invoking. Sadly i've only find on invoking method and it worked fine for setting labels and a bunch of other stuff, but it failed when it came to DataGridViews, Combo- and TextBoxes. This is the invoking "code" i'm talking about:
this.uiObject.Invoke((MethodInvoker)delegate
{
this.uiObject.Text = "Hello World";//Setting Label Text from BackgroundWorker
});
As i said i tried using this on the following code, but it didn't work.
private void loadPlaylists()
{
this.playlistGrid.Rows.Clear();//Invoke on a DataGridView
string filePath = this.genrePath + this.sortBox.SelectedItem.ToString() + ".txt";
if (File.Exists(filePath) && File.ReadAllText(filePath) != "")
{
using (StreamReader sr = new StreamReader(filePath))
{
bool first = false;
string line = "";
while ((line = sr.ReadLine()) != null)
{
if (first && line != "")
{
string[] split = line.Split(new string[] { " // " }, StringSplitOptions.None);
FullPlaylist playList = spotify.GetPlaylist(split[1], split[0]);
this.playlistGrid.Rows.Add(playList.Name, playList.Owner.Id);//Invoke on a DataGridView
}
if (line != "")
first = true;
}
}
}
}
private void loadItems(bool newItem = false, bool deletedItem = false, string name = "")
{
this.sortBox.Items.Clear();//Invoke on a ComboBox
DirectoryInfo dir = new DirectoryInfo(this.genrePath);
foreach (var file in dir.GetFiles("*.txt"))
{
string[] split = file.Name.Split(new string[] { ".txt" }, StringSplitOptions.None);
this.sortBox.Items.Add(split[0]);//Invoke on a ComboBox
}
if (newItem)
{
this.sortBox.SelectedItem = name;//Invoke on a ComboBox
this.mode = 5;
}
if (deletedItem)
{
if (this.sortBox.Items.Count > 0)//Invoke on a ComboBox
{
this.sortBox.SelectedIndex = 0;//Invoke on a ComboBox
this.mode = 5;
}
else
this.playlistGrid.Rows.Clear();//Invoke on a DataGirdView
}
}
private void addPlaylists()
{
string[] split;
string filePath = "";
if (this.sortBox.SelectedIndex != -1)//Invoke on a ComboBox
{
filePath = this.genrePath + this.sortBox.SelectedItem.ToString() + ".txt";//Invoke on a ComboBox
}
else
{
MetroFramework.MetroMessageBox.Show(this, "Select a valid Category first!",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (this.playlistLink.Text != "" && this.playlistLink.Text.Contains("/"))//Invoke on a TextBox
{
if (this.playlistLink.Text.Contains("|"))//Invoke on a TextBox
{
split = this.playlistLink.Text.Split('|');//Invoke on a TextBox
}
else
{
split = new string[1];
split[0] = this.playlistLink.Text;//Invoke on a TextBox
}
for (int j = 0; j < split.Length; j++)
{
string[] split2 = split[j].Split('/');
string id = split2[split2.Length - 1], owner = split2[split2.Length - 3];
FullPlaylist playlist = this.spotify.GetPlaylist(owner, id);
string write = id + " // " + owner + " // " + playlist.Name;
this.changeOrAddLine(filePath, write, write);
}
this.playlistLink.Text = "";//Invoke on a TextBox
this.loadPlaylists();//Call to a Methode, where Invoke is needed
}
else if (!this.playlistLink.Text.Contains("/"))//Invoke on a TextBox
{
//Error
this.playlistLink.Text = "";//Invoke on a TextBox
}
else
{
//Error
}
}
Those are the three methods i'm calling from the BackgrounddWorker. The code is fine and works outside of the BackgroundWorker. I marked all Lines where Invoking(if it's even needed) should be used, because there it's doing something with an UI-Project. I hope someone of you guys is able to show me how to do this. I'm not expecting you to take my code and add the fixes, just a overall example on how to do this should work aswell. Thanks in advance!

Anywhere you affect a UI control, wrap that logic in an invoke call. So for instance, rather than:
this.playlistGrid.Rows.Clear(); // No
Do this:
uiObject.Invoke(() => this.playlistGrid.Rows.Clear()); // Yes
This effectively sends a message to the UI thread to perform that operation when the time is right in the UI's message loop. If you wrap every interaction with your UI controls in an invoke like this, the errors should cease, but beware tht you are blocking the background thread while you wait for the result of the Invoke. Be sure the UI thread doesn't in-turn wait for the background thread or you'll have deadlock. You can avoid this by using BeginInvoke but you do need to be aware of the fact that the operation may not happen immediately. For instance, if you wish to read something from a control, not do this:
string localValue = null;
uiObject.BeginInvoke(() => { localValue = this.sortBox.SelectedItem.ToString(); });
// should NOT assume you can use localValue here
You generally are better off gathering all data from your controls in your UI layer before invoking your async action and passing it to the background process. For example:
private void loadPlaylists(string selectedItem)

Related

How to check each line from an website/php file and Enable/disable Components C#

I try to make a function that allows me to enable and disable multiple components from a server. Preferably from one php file.
Example:
Website Side
AdminPanelEnabled=True
UserIPPanelEnabled=False
GuestPanelEnabled=True
(On the website there is no other code just what you see above)
If it is set to true on the server/website it will enable the component or if set to false it will disable the component.
Tries and fails
Checker = new WebClient().DownloadString("URL/Checker.php");
if (Checker == "AdminPanelEnabled=True")
{
AdminPanel.Enabled = true;
}
else
{
AdminPanel.Enabled = false;
}
if (Checker == "UserIPPanelEnabled=True")
{
UserIPPanel.Enabled = true;
}
else
{
UserIPPanel.Enabled = false;
}
if (Checker == "GuestPanelEnabled=True")
{
GuestPanel.Enabled = true;
}
else
{
GuestPanel.Enabled = false;
}
The file you provided consists of multiple lines, so you have to separate the lines first and then check every single line. So, maybe something like this works?
string[] lines = new WebClient().DownloadString("Checker.php")
.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
foreach (var line in lines)
{
string[] config = line.Split('=');
if (config[0] == "AdminPanelEnabled")
{
AdminPanel.Enabled = bool.Parse(config[1]);
}
else if (config[0] == "UserIPPanelEnabled")
{
UserIPPanel.Enabled = bool.Parse(config[1]);
}
else if (config[0] == "GuestPanelEnabled")
{
GuestPanel.Enabled = bool.Parse(config[1]);
}
}

call back query data from inline keyboard

I'm trying to get the data from an inline keyboard, I've searched a lot but unfortunately didn't get my answer and non of codes worked for me. Here's my code please help me
static void Main(string[] args){
InlineKeyboardButton[][] buttons =
new InlineKeyboardButton[][]{
new InlineKeyboardButton[]{newInlineKeyboardButton() { Text = "show Channel", CallbackData = "Data1" }},
new InlineKeyboardButton[]{new InlineKeyboardButton() { Text = "show Website", CallbackData = "Data2" }}};
inlineKeyboardMarkup = new InlineKeyboardMarkup() { InlineKeyboard = buttons };
Task.Run(() => RunBot());
Console.ReadLine();
} // End of main method
public static async Task RunBot(){
while (true){
var u = await bot.MakeRequestAsync(new GetUpdates() { Offset
= offset });
foreach (var update in u)
{
offset = update.UpdateId + 1;
var text = update.Message.Text;
// here I want to get the data like this, but it doesn't work
if (update.ChosenInlineResult != null){
Console.WriteLine("Chosen Inline Result: " +
update.ChosenInlineResult.ToString());
}
switch(text){
case "Something":{
var req = new SendMessage(update.Message.Chat.Id, "راهنما") { ReplyMarkup = inlineKeyboardMarkup };
await bot.MakeRequestAsync(req);
break;
}
}
}
}
}
you must replace this
if (update.ChosenInlineResult != null){
Console.WriteLine("Chosen Inline Result: " +
update.ChosenInlineResult.ToString());
}
with something like This :
if (update.CallbackQuery != null)
{
Console.WriteLine(val.CallbackQuery.Message+"-"+val.CallbackQuery.Data);
}

c# nullreference for save on load streamreader/writer

I've made a program and I want to save the data. Saving is working, but "Loading" doesn't work.
public void Save(StreamWriter sw)
{
for (int i = 0; i < buecher.Count; i++)
{
Buch b = (Buch)buecher[i];
if (i == 0)
sw.WriteLine("ISDN ; Autor ; Titel");
sw.WriteLine(b.ISDN + ";" + b.Autor + ";" + b.Titel);
}
}
public void Load(StreamReader sr)
{
int isd;
string aut;
string tit;
while (sr.ReadLine() != "")
{
string[] teile = sr.ReadLine().Split(';');
try
{
isd = Convert.ToInt32(teile[0]);
aut = teile[1];
tit = teile[2];
}
catch
{
throw new Exception("umwandlung fehlgeschlagen");
}
Buch b = new Buch(isd, aut, tit);
buecher.Add(b);
}
}
If I'm doing that with an break after buecher.Add(b); than its everything fine but it obviously shows me only 1 book... if I'm not using the break he gives me an error "nullreference.."
Would be awesome if someone could help me
best regards
Ramon
The problem is that you are reading two lines for each iteration in the loop (and throwing away the first one). If there are an odd number of lines in the file, the second call to Read will return null.
Read the line into a variable in the condition, and use that variable in the loop:
public void Load(StreamReader sr) {
int isd;
string aut;
string tit;
// skip header
sr.ReadLine();
string line;
while ((line = sr.ReadLine()) != null) {
if (line.Length > 0) {
string[] teile = line.Split(';');
try {
isd = Convert.ToInt32(teile[0]);
aut = teile[1];
tit = teile[2];
} catch {
throw new Exception("umwandlung fehlgeschlagen");
}
Buch b = new Buch(isd, aut, tit);
buecher.Add(b);
}
}
}
You are calling sr.ReadLine() twice for every line, once in the while() and once right after. You are hitting the end of the file, which returns a null.
Different approach to this but I suggest it because it's simpler;
Load(string filepath)
{
try
{
List<Buch> buches = File.ReadAllLines(filepath)
.Select(x => new Buch(int.Parse(x.Split(';')[0]), x.Split(';')[1], x.Split(';')[2]));
{
catch
{
throw new Exception("umwandlung fehlgeschlagen");
}
}
You could do it in more lines if you find it to be more readable but I've come to prefer File.ReadAllText and File.ReadAllLines to StreamReader approach of reading files.
Instead of using the LINQ statement you could also do;
Load(string filepath)
{
try
{
string[] lines = File.ReadAllLines(filepath);
foreach (string line in lines)
{
string[] tokens = line.Split(';');
if (tokens.Length != 3)
// error
int isd;
if (!int.TryParse(tokens[0], out isd))
//error, wasn't an int
buetcher.Add(new Buch(isd, tokens[1], tokens[2]);
}
{
catch
{
throw new Exception("umwandlung fehlgeschlagen");
}
}

Massive differences in reexecution

I wrote a little C# application that indexes a book and executes a boolean textretrieval algorithm on the index. The class at the end of the post showes the implementation of both, building the index and executing the algorithm on it.
The code is called via a GUI-Button in the following way:
private void Execute_Click(object sender, EventArgs e)
{
Stopwatch s;
String output = "-----------------------\r\n";
String sr = algoChoice.SelectedItem != null ? algoChoice.SelectedItem.ToString() : "";
switch(sr){
case "Naive search":
output += "Naive search\r\n";
algo = NaiveSearch.GetInstance();
break;
case "Boolean retrieval":
output += "boolean retrieval\r\n";
algo = BooleanRetrieval.GetInstance();
break;
default:
outputTextbox.Text = outputTextbox.Text + "Choose retrieval-algorithm!\r\n";
return;
}
output += algo.BuildIndex("../../DocumentCollection/PilzFuehrer.txt") + "\r\n";
postIndexMemory = GC.GetTotalMemory(true);
s = Stopwatch.StartNew();
output += algo.Start("../../DocumentCollection/PilzFuehrer.txt", new String[] { "Pilz", "blau", "giftig", "Pilze" });
s.Stop();
postQueryMemory = GC.GetTotalMemory(true);
output += "\r\nTime elapsed:" + s.ElapsedTicks/(double)Stopwatch.Frequency + "\r\n";
outputTextbox.Text = output + outputTextbox.Text;
}
The first execution of Start(...) runs about 700µs, every rerun only takes <10µs.
The application is compiled with Visual Studio 2010 and the default 'Debug' buildconfiguration.
I experimentad a lot to find the reason for that including profiling and different implementations but the effect always stays the same.
I'd be hyppy if anyone could give me some new ideas what I shall try or even an explanation.
class BooleanRetrieval:RetrievalAlgorithm
{
protected static RetrievalAlgorithm theInstance;
List<String> documentCollection;
Dictionary<String, BitArray> index;
private BooleanRetrieval()
: base("BooleanRetrieval")
{
}
public override String BuildIndex(string filepath)
{
documentCollection = new List<string>();
index = new Dictionary<string, BitArray>();
documentCollection.Add(filepath);
for(int i=0; i<documentCollection.Count; ++i)
{
StreamReader input = new StreamReader(documentCollection[i]);
var text = Regex.Split(input.ReadToEnd(), #"\W+").Distinct().ToArray();
foreach (String wordToIndex in text)
{
if (!index.ContainsKey(wordToIndex))
{
index.Add(wordToIndex, new BitArray(documentCollection.Count, false));
}
index[wordToIndex][i] = true;
}
}
return "Index " + index.Keys.Count + "words.";
}
public override String Start(String filepath, String[] search)
{
BitArray tempDecision = new BitArray(documentCollection.Count, true);
List<String> res = new List<string>();
foreach(String searchWord in search)
{
if (!index.ContainsKey(searchWord))
return "No documents found!";
tempDecision.And(index[searchWord]);
}
for (int i = 0; i < tempDecision.Count; ++i )
{
if (tempDecision[i] == true)
{
res.Add(documentCollection[i]);
}
}
return res.Count>0 ? res[0]: "Empty!";
}
public static RetrievalAlgorithm GetInstance()
{
Contract.Ensures(Contract.Result<RetrievalAlgorithm>() != null, "result is null.");
if (theInstance == null)
theInstance = new BooleanRetrieval();
theInstance.Executions++;
return theInstance;
}
}
Cold/warm start of .Net application is usually impacted by JIT time and disk access time to load assemblies.
For application that does a lot of disk IO very first access to data on disk will be much slower than on re-run for the same data due to caching content (also applies to assembly loading) if data is small enough to fit in memory cache for the disk.
First run of the task will be impacted by disk IO for assemblies and data, plus JIT time.
Second run of the same task without restart of application - just reading data from OS memory cache.
Second run of application - reading assemblies from OS memory cache and JIT again.

How to optimize this code to create document libraries

This is sharepoint code, but I know c# developers would understand it.
I cant think a way right now to optimize it.
The idea is to create a document library based on the creation of an event, The name of the document library is the startdate in some format + the event title.
The problem is when the user makes many events, the same day, with the same title.
I did it with an IF for only one occurence of the duplication. But there should be another better way to do it.
The idea is to concatenate a number at the end of the doc library /1/2/3 etc.
using (SPSite oSPSite = new SPSite(SiteUrl))
{
using (SPWeb oSPWeb = oSPSite.RootWeb)
{
if (oSPWeb.Lists[DocumentLibraryName] == null)
{
Guid ID = oSPWeb.Lists.Add(DocumentLibraryName, DocumentLibraryName + System.DateTime.Now.ToString(), SPListTemplateType.DocumentLibrary);
SPList oSPList = oSPWeb.Lists[ID];
DocumentLibraryLink = oSPList.DefaultViewUrl;
oSPList.OnQuickLaunch = false;
oSPList.Update();
}
else
{
if (oSPWeb.Lists[DocumentLibraryName + "/1"] == null)
{
Guid ID = oSPWeb.Lists.Add(DocumentLibraryName + "/1", DocumentLibraryName + System.DateTime.Now.ToString(), SPListTemplateType.DocumentLibrary);
SPList oSPList = oSPWeb.Lists[ID];
DocumentLibraryName = DocumentLibraryName + "/1";
DocumentLibraryLink = oSPList.DefaultViewUrl;
oSPList.OnQuickLaunch = false;
oSPList.Update();
}
}
}
}
}
In pseudo-code:
string docLibNameBase ="myLibname";
string docLibNameTemp = docLibNameBase; //we start with the calculated title
int iCounter = 1;
//we check if the currently calculated title is OK
while (listExists(docLibNameTemp, yourWeb)) {
docLibNameTemp = docLibNameBase + "/" + iCounter.toString();
}
//this is where you create the new list using docLibNameTemp as a good title
bool listExists(string docLibName, SPWeb web){
try {
//if there is no list with such name, it will throw an exception
return (web.Lists[docLibname]!=null);
} catch{
return false;
}
}

Categories