I am updating a "timer" field in my listView from different threads. It works fine, the problem is just that it flickers. This is the code each thread is calling when it needs to be updated (almost every second).
private void AddToListView(string user, string status, string proxy, int number)
{
Invoke(new MethodInvoker(
delegate
{
listView1.BeginUpdate();
this.listView1.Items[number].SubItems[1].Text = status;
listView1.EndUpdate();
}
));
}
Having Googled a bit im not even sure i can make this flicker go away? :/
I would not use Invoke here. In fact, in most cases it is usually not a great option despite what you may read on the internet. Instead, package up the data being generated by the thread into a POCO and put it into a queue. Have a System.Windows.Forms.Timer tick every second with the event handler pulling items out of the queue to update the ListView in batches. Also, try setting DoubleBuffered to true. These suggestions should help some.
public class YourForm : Form
{
private ConcurrentQueue<UpdateInfo> queue = new ConcurrentQueue<UpdateInfo>();
private void YourTimer_Tick(object sender, EventArgs args)
{
UpdateInfo value;
listView1.BeginUpdate();
while (queue.TryDequeue(out value)
{
this.listView1.Items[value.Number].SubItems[1].Text = value.Status;
}
listView1.EndUpdate();
}
private void SomeThread()
{
while (true)
{
UpdateInfo value = GetUpdateInfo();
queue.Enqueue(value);
}
}
private class UpdateInfo
{
public string User { get; set; }
public string Status { get; set; }
public string Proxy { get; set; }
public int Number { get; set; }
}
}
Related
Don't now if title is clear. Here is a piece of code from a class in charge of managing a long operation :
public class LongProcess
{
public delegate void RunningChangedEventHandler(bool running);
public event RunningChangedEventHandler RunningChanged;
private object runningLock = new object();
public bool Running
{
get { lock (runningLock) { return mRunning; } }
set
{
lock (runningLock)
{
RunningChanged.Invoke(value);
value = mRunning;
}
}
}
public void start()
{
mWorker = new BackgroundWorker();
mWorker.DoWork += Bg_DoWork;
mWorker.RunWorkerAsync();
}
private void Bg_DoWork(object sender, DoWorkEventArgs e)
{
Running = true;
// Some things to do here ... but I need Running to be equals to true and it is not
}
}
In main programm, I use LongProcess to start some tasks, it is completed by report progression etc ...
The only problem I'm facing, is that it seems that I'm unable to set "Running" to true. Even right after the call to the setter, it still keeps its old value.
Any help and explanations on how this works will be greatly appreciated !
You have your value and field the wrong way around in the setter. You need this:
public bool Running
{
get { lock (runningLock) { return mRunning; } }
set
{
lock (runningLock)
{
RunningChanged.Invoke(value);
mRunning = value; // <=== LOOK HERE
}
}
}
I am using Facebook Sdk C# To develop a desktop program for publication posts in Facebook groups. The software will publish very quickly I need a way to control the speed of publication and capping for publication not less than 10 seconds between each publication and the other. How to do like this methods ?
My class
public static string UploadPost(string groupid, string intTitle, string inMessage, string inLinkCaption, string inLinkUrl, string inLinkDescription, string inLinkUrlPicture)
{
object obj;
Facebook.JsonObject jsonObj;
FacebookClient client;
string access_token = AppSettings.Default.AccessToken.ToString();
client = new FacebookClient(access_token);
var args = new Dictionary<string, object>();
args["message"] = inMessage;
args["caption"] = inLinkCaption;
args["description"] = inLinkDescription;
args["name"] = intTitle;
args["picture"] = inLinkUrlPicture;
args["link"] = inLinkUrl;
if ((obj = client.Post("/" + groupid + "/feed", args)) != null)
{
if ((jsonObj = obj as Facebook.JsonObject) != null)
{
if (jsonObj.Count > 0)
return jsonObj[0].ToString();
}
}
return string.Empty;
}
internal static bool UploadPost(string p1, string p2)
{
throw new NotImplementedException();
}
}
}
My submit button
private void btnPost_Click(object sender, EventArgs e)
{
for (int i = 0; i < lstgroupsbox.Items.Count; i++)
{
if (Class1.UploadPost(lstgroupsbox.Items[i].ToString(), "amine", txtStatus.Text, "googl", txtLink.Text, "seach", txtImagePath.Text) != string.Empty)
label23.Text=""+lstgroups.Items[i].Text;
}
//foreach (var item in lstgroupsbox.Items)
//{
// if (Class1.UploadPost(item.ToString(), "amine", txtStatus.Text, "googl", 2, "seach", txtImagePath.Text) != string.Empty)
// label23.Text=""+lstgroups.Items[i].Text;
//}
}
I suggest you look into the Timer class. This one way you could do this:
Create a ConcurrentQueue (not a normal Queue because it's not thread-safe, look into thread safety) in your main class. This is your upload "job list". Add also a Timer and create an event handler method for its Elapsed event (refer to the first link in this answer for instructions). The event handler method is what will execute your jobs.
Then create a new class that holds a post's info and the details needed to upload it. This is your upload job class.
In your for loop inside your submit button's event handler, instead of uploading the images, you create instances of that job class and enqueue them into your job list (the ConcurrentQueue). After they're all added, you start your main class' Timer. The Elapsed event handler method mentioned earlier will take the next item from the queue (or stop if it's empty?) and upload it to Facebook.
EDIT:
So, in your form class, add a using statement first:
using System.Collections.Concurrent;
Then add these near the top of the class:
private System.Timers.Timer _jobTimer = new Timer(10000);
private ConcurrentQueue<UploadJob> _jobQueue = new ConcurrentQueue<UploadJob>();
These go to your form's constructor (after the InitializeComponent() method call):
_jobTimer.SynchronizingObject = this;
// ^ The Elapsed event will be run on the same thread as this.
// This way we won't get exceptions for trying to access the form's labels
// from another thread (the Timer is run on its own thread).
_jobTimer.Elapsed += OnJobTimedEvent;
Then you add the OnJobTimedEvent method somewhere in your form class:
private void OnJobTimedEvent(object sender, ElapsedEventArgs e)
{
UploadJob job;
if (_jobQueue.TryDequeue(out job)) // Returns false if it fails to return the next object from the queue
{
if (Class1.UploadPost(job.Group,
job.Name,
job.Message,
job.Caption,
job.Link,
job.Description,
job.Picture) != string.Empty)
{
// Post was uploaded successfully
}
}
else
{
// I believe we can assume that the job queue is empty.
// I'm not sure about the conditions under which TryDequeue will fail
// but if "no more elements" isn't the only one, we could add
// (_jobQueue.Count == 0)
// to the if statement above
_jobTimer.Stop();
// All uploads complete
}
}
As you can see, it uses UploadJob. That class can be separated into a separate file altogether:
public class UploadJob
{
public string Group { get; protected set; }
public string Name { get; protected set; }
public string Message { get; protected set; }
public string Caption { get; protected set; }
public string Link { get; protected set; }
public string Description { get; protected set; }
public string Picture { get; protected set; }
public UploadJob(string group,
string name,
string message,
string caption,
string link,
string description,
string picture)
{
Group = group;
Name = name;
Message = message;
Caption = caption;
Link = link;
Description = description;
Picture = picture;
}
}
and finally we get to your button click event handler:
private void btnPost_Click(object sender, EventArgs e)
{
for (int i = 0; i < lstgroupsbox.Items.Count; i++)
{
_jobQueue.Enqueue(lstgroupsbox.Items[i].ToString(),
"amine",
txtStatus.Text,
"googl",
txtLink.Text,
"seach",
txtImagePath.Text);
}
_jobTimer.Start();
}
Personally I would probably separate all this into an UploadManager class or something and let that class worry about the timer and everything, but this should work just fine.
I was given a generic API class, that contains a custom event which always needs to be invoked by the main UI thread.
My job is to banish these invocation call from the custom class, to make it "painless".
It should be synchronized like the default events in WinForms (eg the Timer "Elapsed" event, which also needs no invocation when it published values to a text box)
Is it possible to solve this, since the custom class needs to know where to invoke?
Here's the (important part of the) code:
public class ContactSensorHelper
{
public event OnReleaseStateChanged ReleaseStateChanged;
public delegate void OnReleaseStateChanged(ContactSensorEventArgs e);
private ContactSensorEventArgs.ReleaseState recentReleaseState;
public void ReportStateChanged()
{
if (ReleaseStateChanged != null)
ReleaseStateChanged(new ContactSensorEventArgs()
{
State = recentReleaseState
});
}
public class ContactSensorEventArgs : EventArgs
{
//......
public ReleaseState State { get; set; }
//......
public enum ReleaseState
{
FullReleased,
PartlyReleased,
NotReleased
}
}
}
The call from main UI:
public void SensorInit()
{
//....
sensorHelper.ReleaseStateChanged += releaseStateChanged;
//....
}
private void releaseStateChanged(ContactSensorEventArgs e)
{
//example
textBox1.Text = e.State.ToString(); // Thread exception (obviously)
}
Does anybody have me a hint to start?
You could do this by using your own event calling, and storing a reference to the thread, when the event is attached.
With the event add/remove syntax, you can have the caller attach to the event like before, but internally you store a list, with a reference to the thread (using an AsyncOperation) and the delegate to be called (used a Tuple containing both in the example)
Below is an example. I tested it, and it worked as expected when testing, but you might have to add some locking of the list to make it thread safe in case events are added/removed simultaneously.
public class ContactSensorHelper:IDisposable
{
public delegate void OnReleaseStateChanged(ContactSensorEventArgs e);
private ContactSensorEventArgs.ReleaseState recentReleaseState;
public void ReportStateChanged()
{
if (statechangedList.Count > 0)
{
var e = new ContactSensorEventArgs()
{
State = recentReleaseState
};
statechangedList.ForEach(t =>
t.Item1.Post(o => t.Item2((ContactSensorEventArgs)o), e));
}
}
List<Tuple<AsyncOperation, OnReleaseStateChanged>> statechangedList = new List<Tuple<AsyncOperation,OnReleaseStateChanged>>();
public event OnReleaseStateChanged ReleaseStateChanged
{
add
{
var op = AsyncOperationManager.CreateOperation(null);
statechangedList.Add(Tuple.Create(op, value));
}
remove
{
var toremove = statechangedList.Where(t => t.Item2 == value).ToArray();
foreach (var t in toremove)
{
t.Item1.OperationCompleted();
statechangedList.Remove(t);
}
}
}
public void Dispose()
{
statechangedList.ForEach(t => t.Item1.OperationCompleted());
statechangedList.Clear();
}
public class ContactSensorEventArgs : EventArgs
{
//......
public ReleaseState State { get; set; }
//......
public enum ReleaseState
{
FullReleased,
PartlyReleased,
NotReleased
}
}
}
Using C# .NET 4.0, Visual Studio 2010.
Well at the moment I'm looking into de-coupling of Classes and using interfaces.
I've implemented a Solution from another post to test if I could get it working but unfortunately I have never used an interface ever.
So here's the basics of what I have:
Form1:
partial class Form1 : InterfacePareto
{
public string myTest
{
get { return herpTxt.Text; }
set { herpTxt.Text = value; }
}
}
Interface:
interface InterfacePareto
{
string myTest { get; set; }
}
MyWorkingOutClass:
Class MyWorkingOutClass
{
private readonly InterfacePareto pare;
public MyWorkingOutClass(InterfacePareto pare)
{
this.pare = pare;
}
private void Testtime()
{
string firstName = pare.myTest;
pare.myTest = firstName + " extra";
}
}
The purpose:
The plan at the moment is to get the text from the forms textbox. Then pass it to the working class. The working class then does whatever calculations etc needed, then passes the result back to the forms textbox.
My question is, is my code along the right tracks. If yes, then what am I missing/doing wrong? Or if anyone thinks this is not the right way of achieving what I need, do they have any suggestions?
Many thanks!
I've just tested code and this works fine for me:
public partial class MainForm :Form, InterfacePareto //My main form inheriting Form class and interface
{
public MainForm()
{
InitializeComponent();
}
public string myTest
{
get { return herpTxt.Text; }
set { herpTxt.Text = value; }
}
private void button1_Click(object sender, EventArgs e)
{
//On button click create MyWorkingOutClass instance and pass MainForms instance
MyWorkingOutClass mc = new MyWorkingOutClass(this);
//After this line text box content will change
mc.Testtime();
}
}
//Changed modifier to public
public interface InterfacePareto
{
string myTest { get; set; }
}
//Changed modifier to public
public class MyWorkingOutClass
{
private readonly InterfacePareto pare;
public MyWorkingOutClass(InterfacePareto pare)
{
this.pare = pare;
}
//Changed modifier to public
public void Testtime()
{
string firstName = pare.myTest;
pare.myTest = firstName + " extra";
}
}
This should work fine.
There is one issue you will get when the MyWorkingOutClass does its work on a different thread than the UI thread.
To solve that you might want to change the implementation on the form to switch to the UI thread.
i have this poll class
class Poll
{
public string question { get; set; }
public Timer pollTimer { get; set; }
public List<string> userVoted { get; set; }
public Dictionary<string, int> choices { get; set; }
public bool PollRunning { get; set; }
public Poll(string question,Dictionary<string,int> choices)
{
this.question = question;
this.choices = choices;
this.pollTimer = new Timer(15000);
this.PollRunning = true;
this.userVoted = new List<string>();
}
public string pollResults()
{
string temp = "";
foreach (KeyValuePair<string, int> keyValuePair in choices)
{
temp = temp + keyValuePair.Key + " " + keyValuePair.Value + ", ";
}
return string.Format("Poll Results: {0}", temp);
}
}
and I have this code in a StartPool method
static Dictionary<Channel, Poll> polls = new Dictionary<Channel, Poll>();
public void startPool(Channel channel)
{
polls.Add(channel, new Poll(question, tempdict));
polls[channel].pollTimer.Elapsed += new ElapsedEventHandler(pollTimer_Elapsed);
polls[channel].pollTimer.Start();
}
When this method gets called
static void pollTimer_Elapsed(object sender, ElapsedEventArgs e)
{
//do stuff to the poll that called this.
}
I need know what poll object's timer is calling this method
so I can do polls[channel].pollTimer.Stop(); and do polls[channel].pollResults();
As it is I have no idea which poll stop and post results for when this runs
i'm willing to post entire solution if that will help you help me.
The problem with the way you've designed the Poll class is that the Poll class doesn't completely do its job. You require other classes to know how to start and stop polling, meaning half of the polling implementation is inside the Poll class and half of the implementation is outside the Poll class. If you're going to create a Poll class, hide ALL the implementation details from everyone else.
Here is what I mean. I would create an event in Poll like this:
public event EventHandler<ElapsedEventArgs> Elapsed;
In Poll's constructor, add this line:
this.pollTimer.Elapsed += pollTimer_elapsed;
and the pollTimer_elapsed looks like this:
private void pollTimer_elapsed(object sender, ElapsedEventArgs e)
{
var han = this.Elapsed;
if (han != null)
han(this, e); // Fire the Elapsed event, passing 'this' Poll as the sender
}
Add a new public method in Poll to start the timer:
public void Start()
{
this.pollTimer.Start();
}
So now your startPool method looks like this:
public void startPool(Channel channel)
{
polls.Add(channel, new Poll(question, tempdict));
polls[channel].Elapsed += poll_Elapsed;
polls[channel].Start();
}
static void poll_Elapsed(object sender, ElapsedEventArgs e)
{
//sender is now a Poll object
var poll = sender as Poll;
// Now you can do poll.pollTimer.Stop()
// Or better yet, add a Stop method to the Poll class and call poll.Stop()
}
IMHO this approach is slightly better because the Poll object is hiding more of its implementation from external objects. From startPool's point of view, the Poll class is simpler to use, and you also don't require anything outside of your Poll class to know about Timers.
you can add a property :
public bool pollTimerElapsed { get; set; }
and subscribe a handler in the contsructeur of Poll of Elapsed event of pollTimer where you set to true the property pollTimerElapsed
then you can filter elapsed Polls by this property