I am developing an application that uses a progressbar to show the user any development in the program. The program I am writing uses a progressbar to show the user how many packets of data have been sent in the course of execution. I have created an event in the underlying library that triggers once another packet has been transmitted. Here are the event lines I have set up:
public delegate void ChangedEventHandler(object sender, EventArgs e);
public event ChangedEventHandler PercentageUpdate;
protected internal virtual void OnPercentageChanged(EventArgs e)
{
if (PercentageUpdate != null) PercentageUpdate(this, e);
}
Note that the above code is set up in the underlying library. I have the event triggered in this library like so:
//reinitializing is extraneous, as Receive() calls are overwriting
try
{
fsa.rnd = fsa.TransferSocket.Receive(fsa.File_Buffer, 0, FSArgs.BlockSize, SocketFlags.None);
}
catch (Exception e)
{
fsa.Dispose();
throw new GeneralNetworkingException("FileSocket receive() failed!", e);
}
fsa.tot += Convert.ToInt64(fsa.rnd);
fsa.TransferPercentage = (fsa.tot/fsa.FileSize) * 100;
fsa.OnPercentageChanged(EventArgs.Empty); //throw event for form
Finally, in the application, I have the event initialized like so:
public delegate void UpdatePerc(int index);
f_list[f_list.Count-1].fsa.PercentageUpdate += (sender, e) => filesocket_percentage_updated(sender, e, sel_index);
private void filesocket_percentage_updated(object sender, EventArgs e, int index)
{
UpdateP(index);
}
private void UpdateP(int index)
{
if (progressBar1.InvokeRequired)
{
this.BeginInvoke(new UpdatePerc(UpdateP), new object[] { index });
}
else
{
if (sel_index == index) //then redraw progressbar
{
if (x_list[index] > 1)
{
y_list[index]++;
if (((int)(y_list[index] % x_list[index])) == 0)
{
z_list[index]++;
progressBar1.Increment(1);
progressBar1.Update();
}
}
else
{
z_list[index]++;
progressBar1.Increment(1);
progressBar1.Update();
richTextBox1.Text += (z_list[index]+ '\n');
}
}
else
{
if (x_list[index] > 1)
{
y_list[index]++;
if (((int)(y_list[index] % x_list[index])) == 0)
{
z_list[index]++;
}
}
else
{
z_list[index]++;
}
}
}
}
As you can see I am trying to invoke the progressbar to update on a parallel thread. However, nothing happens at all. Any help would be appreciated!
Thanks.
Related
I am receiving messages from MSMQ. An event is fired when a message is received, in some situations a delay be required before the event is fired. At the moment I have a Task.Delay to wait for the specified time before firing the event. I am wondering if anyone has a better solution or can see any problems in my current solution:
private List<Task> _delayTasks = new List<Task>();
private void PeekComplete(object sender, msmq.PeekCompletedEventArgs e)
{
//..code to get mesage off the queue...
double delay = _messageTimeOut.TimeOutRequired(messageBody);
if (delay > 0)
{
CreateDelayTask(delay, messageBody);
WaitDelays();
}
else
{
_OnMessageReceived?.Invoke(messageBody);
ProcessingCounter.Decrement();
}
GetNextMessage();
}
private void WaitDelays()
{
while (_delayTasks.Count > 0)
{
int index = -1;
try
{
index = Task.WaitAny(_delayTasks.ToArray());
}
finally
{
if (index > -1)
_delayTasks.RemoveAt(index);
}
}
}
private void CreateDelayTask(double milliSecondsTimeOut, string messageBody)
{
var delay = (int)Math.Ceiling(milliSecondsTimeOut);
var task = Task.Delay(delay).ContinueWith((antecedent) =>
{
try
{
_OnMessageReceived?.Invoke(messageBody);
}
catch (Exception ex)
{
_OnMessageReceivedError?.Invoke(ex, messageBody);
}
finally
{
ProcessingCounter.Decrement();
}
});
_delayTasks.Add(task);
}
so bascially i have a console application acting as a client software receiving data from a WCF feed. this works just fine when i want to do a console.writeline and print the data i'm getting in the console. I don't control the service end of the WCF feed so i have to use this console client software to access the data.
I'm trying to build an ASP.net web api application to pass this data to my own client via REST api. There are other complex reasons i have to do it this way but when it comes down to it i have to. I've built the basic web api for doing a GET to get the information. added the console application as a resource to the web api application but get an error message when I make the GET call.
This is the URL i'm using to make the GET call.
http://localhost:60421/api/CallData?skillNumber=92
After i make this call i get the below error message
[ERROR] System.InvalidOperationException occurred
HResult=0x80131509
Message=Could not find default endpoint element that references contract 'FeedService.IFeedService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
Source=
StackTrace:
The error occurs in this cs file. I've commented at the line it occurs in.
using ScoreBoardClientTest.FeedService;
namespace ScoreBoardClientTest
{
public class FeedServiceAgent : IFeedServiceAgent, IFeedServiceCallback
{
private static FeedServiceClient _feedServiceClient;
private ConnectionStats.ConnectionStatus _connectionStatus;
private bool _retrying;
private bool _disposed;
public FeedServiceAgent() //(IEventAggregator eventAggregator)
{
//Guard.ArgumentNotNull(eventAggregator, "eventAggregator");
//_eventAggregator = eventAggregator;
InitializeServiceClient();
}
public event MessageReceivedEventHandler MessageReceived;
public void InitializeServiceClient()
{
// The error message occurs at the line right below this
_feedServiceClient = new FeedServiceClient(new InstanceContext(this));
_feedServiceClient.InnerChannel.Opening += OnOpening;
_feedServiceClient.InnerChannel.Opened += OnOpened;
_feedServiceClient.InnerChannel.Closing += OnClosing;
_feedServiceClient.InnerChannel.Closed += OnClosed;
_feedServiceClient.InnerChannel.Faulted += OnFaulted;
}
private void DisposeServiceClient()
{
if (_feedServiceClient == null)
return;
try
{
_feedServiceClient.InnerChannel.Opening -= OnOpening;
_feedServiceClient.InnerChannel.Opened -= OnOpened;
_feedServiceClient.InnerChannel.Closing -= OnClosing;
_feedServiceClient.InnerChannel.Closed -= OnClosed;
_feedServiceClient.InnerChannel.Faulted -= OnFaulted;
_feedServiceClient.Abort();
}
catch
{
//Don't care.
}
finally
{
_feedServiceClient = null;
}
}
public ConnectionStats.ConnectionStatus ConnectionStatus
{
get { return _connectionStatus; }
set
{
_connectionStatus = value;
PublishConnectionStatus();
}
}
private void PublishConnectionStatus()
{
}
private void ProcessCmsData(A cmsData)
{
if (cmsData == null)
return;
var skill = new Skill();
var agents = new List<Agent>();
var cmLookupdata = new List<CmLookupData>();
// LookupData lookupdata = new LookupData();
if (cmsData.C != null && cmsData.C.Length > 0)
LookupDataTranslator.Translate(cmsData.C, cmLookupdata);
if (cmsData.AMember != null)
SkillTranslator.Translate(cmsData.AMember, skill, cmLookupdata);
if (cmsData.B != null && cmsData.B.Length > 0)
AgentTranslator.Translate(cmsData.B, agents, cmsData.AMember.A, cmsData.AMember.CmId); // passing skill params to validate the cmid to discard bad data
var mappedCmsData = new CmsData(skill, agents, cmLookupdata);
if (MessageReceived != null)
MessageReceived(this, new MessageReceivedEventArgs(mappedCmsData, null));
}
#region FeedServiceClient Channel Events
private void OnOpening(object sender, EventArgs eventArgs)
{
_connectionStatus = ConnectionStats.ConnectionStatus.Connecting;
}
private void OnOpened(object sender, EventArgs eventArgs)
{
_connectionStatus = ConnectionStats.ConnectionStatus.Connected;
}
private void OnClosing(object sender, EventArgs eventArgs)
{
_connectionStatus = ConnectionStats.ConnectionStatus.Disconnecting;
}
private void OnClosed(object sender, EventArgs eventArgs)
{
_connectionStatus = ConnectionStats.ConnectionStatus.Disconnected;
}
private void OnFaulted(object sender, EventArgs eventArgs)
{
_connectionStatus = ConnectionStats.ConnectionStatus.Disconnected;
if (!_retrying)
ThreadPool.QueueUserWorkItem(delegate
{
Reconnect();
});
}
#endregion
private void Reconnect()
{
_retrying = true;
_connectionStatus = ConnectionStats.ConnectionStatus.Reconnecting;
// We don't want each client attempting the first reconnect all at the same time.
var random = new Random();
int randomWaitValue = random.Next(1, 10000);
Thread.Sleep(randomWaitValue);
// Try reconnecting 10 times.
for (int i = 1; i <= 10; i++)
{
try
{
DisposeServiceClient();
_feedServiceClient = new FeedServiceClient(new InstanceContext(this));
_feedServiceClient.Open();
_feedServiceClient.InnerChannel.Opening += OnOpening;
_feedServiceClient.InnerChannel.Opened += OnOpened;
_feedServiceClient.InnerChannel.Closing += OnClosing;
_feedServiceClient.InnerChannel.Closed += OnClosed;
_feedServiceClient.InnerChannel.Faulted += OnFaulted;
_connectionStatus = ConnectionStats.ConnectionStatus.Reconnected;
_retrying = false;
//_logger.Info(String.Format("The Scoreboard Client was able to reconnect after {0} retries.", i)) ;
return;
}
catch (Exception exception)
{
//_logger.Error(String.Format("The Scoreboard Client is unable to reconnect: {0}", exception)) ;
// Wait 30 seconds between retries to reduce network congestion.
Thread.Sleep(30000);
}
}
//_logger.Info("The Scoreboard Client was unable to reconnect after 10 retries.") ;
_connectionStatus = ConnectionStats.ConnectionStatus.UnableToConnect;
}
#region Implementation of IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
if (disposing)
{
// Dispose managed resources here.
DisposeServiceClient();
}
_disposed = true;
}
#endregion
public void NotifyCmsData(A cmsData)
{
ThreadPool.QueueUserWorkItem(delegate
{
ProcessCmsData(cmsData);
});
}
public void Subscribe(string eventTopic, int cmId)
{
if (String.IsNullOrEmpty(eventTopic))
return;
InvokeAction(x => x.Subscribe(eventTopic, cmId));
}
public void Unsubscribe(string eventTopic, int cmId)
{
if (String.IsNullOrEmpty(eventTopic))
return;
InvokeAction(x => x.Unsubscribe(eventTopic, cmId));
}
public void RefreshCmsData()
{
throw new NotImplementedException();
}
public LookupData GetLookupData()
{
LookupData lookupdata = new LookupData();
try
{
LookupDataTranslator.Translate(_feedServiceClient.GetLookupData(), lookupdata);
}
catch (Exception e)
{
//if (_logger != null)
// _logger.Error("Exception in finding the lookup data. Exception:" + e.Message);
throw e;
}
return lookupdata;
}
private void InvokeAction(Action<IFeedService> action)
{
try
{
action(_feedServiceClient);
}
catch (Exception exception)
{
//_logger.Error(" Exception in FeedService InvokeAction:" + exception.ToString());
_connectionStatus = ConnectionStats.ConnectionStatus.UnableToConnect;
}
}
}
}
The console application has a properly configured config file for the console application which is what the error message suggests does not exist. also, as i said above the console application functions fully by itself.
QUESTION
How do you use a WCF console application as a resource for a web api successfully?
I had to include the FeedService web URL inside of the web api service as long as the console application
I've written a simple async TCP-Server - it works well. But now I want to make an output of the received Data on the Console-Testprogram. And the problem is, this isn't working! If I connect the MainThread to the EventHandler the program does nothing. Debug is showing that the sc05Server_DataAvailable was called but then nothing happened. The program is still responsive.
Here The Code:
private void ReadCallback(IAsyncResult asyncResult)
{
Sc05BdClient sc05BdClient = asyncResult.AsyncState as Sc05BdClient;
if (sc05BdClient == null) return;
NetworkStream networkStream = sc05BdClient.NetworkStream;
int read = networkStream.EndRead(asyncResult);
if (read == 0)
{
lock (clients)
{
clients.Remove(sc05BdClient);
return;
}
}
string data = Encoding.GetString(sc05BdClient.Buffer, 0, read);
System.Diagnostics.Debug.Print(data);
OnDataAvailable(this, new DataAvailableEventArgs(data)); <---- here Handler is called
networkStream.BeginRead(sc05BdClient.Buffer, 0, sc05BdClient.Buffer.Length, ReadCallback, sc05BdClient);
}
public event EventHandler<DataAvailableEventArgs> DataAvailable;
protected virtual void OnDataAvailable(object sender, DataAvailableEventArgs e)
{
EventHandler<DataAvailableEventArgs> handler = DataAvailable;
if (handler != null)
handler(sender, e);
}
public class DataAvailableEventArgs : EventArgs
{
public string Data;
public DataAvailableEventArgs(string data)
{
Data = data;
}
}
The Main program:
class Program
{
static void Main()
{
Sc05BdServer sc05BdServer = new Sc05BdServer(IPAddress.Any, 2006);
sc05BdServer.DataAvailable += sc05BdServer_DataAvailable;
sc05BdServer.Start();
Console.ReadKey();
sc05BdServer.Stop();
}
static void sc05BdServer_DataAvailable(object sender, DataAvailableEventArgs e)
{
Console.WriteLine(e.Data); <--- this is called once
}
}
I think it has something to do with Threading - but I have no idea how to work with them.
You are probably experiencing some kind of race issue although Console should be immune to that. Check this question but note that I couldn't reproduce the problem: Strange behaviour of Console.ReadKey() with multithreading
I'm developing a program that receives some data and after processing I want to print it.It should be automatic printing.The data is added as records to printList queue.Then a thread is supposed to print them one by one.here's the code :
private void button4_Click(object sender, EventArgs e)
{
rwl.AcquireWriterLock(10);
try
{
if (automaticPrint == false)
{
automaticPrint = true;
_automaticPrintThread = new Thread(new ThreadStart(AutomaticPrintA4));
_automaticPrintThread.IsBackground = true;
_automaticPrintThread.Start();
}
else
{
automaticPrint = false;
if (_automaticPrintThread != null)
{
_automaticPrintThread.Join(1);
}
}
}
finally
{
rwl.ReleaseWriterLock();
}
}
private void AutomaticPrintA4()
{
try
{
this.AutomaticPrintA4Delegate();
}
catch (Exception e)
{
this._automaticPrintThread.Abort();
MessageBox.Show(e.StackTrace);
}
}
private void AutomaticPrintA4Delegate()
{
try
{
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(AutomaticPrintA4Delegate));
else
{
rwl.AcquireReaderLock(100);
Telerik.Reporting.Processing.ReportProcessor rp = new Telerik.Reporting.Processing.ReportProcessor();
System.Drawing.Printing.PrinterSettings ps = new System.Drawing.Printing.PrinterSettings();
try
{
while (automaticPrint)
{
rwlprintlist.AcquireReaderLock(10);
try
{
if (Session.printList != null)
{
if (Session.printList.Count != 0)
{
if (Session.printList[0] != null)
{
rp.PrintReport(new Report(Session.printList[0]), ps);
LockCookie lc = rwlprintlist.UpgradeToWriterLock(10);
Session.printList.RemoveAt(0);
rwlprintlist.DowngradeFromWriterLock(ref lc);
}
}
else
{
Thread.Sleep(1000);
}
}
else
{
Thread.Sleep(1000);
}
}
finally
{
rwlprintlist.ReleaseReaderLock();
}
}
}
finally
{
rwl.ReleaseReaderLock();
}
}
}
catch (Exception e)
{
MessageBox.Show("Print : " + e.StackTrace + e.Message);
}
}
A button click controls automaticprint variable.
rwl controls access to automatic print and rwlprintlist controls access to printList.
but my main gui hangs whenever I start this thread.I don't know why?
P.S. any other design ideas would be appreciated.
In your background worker you call AutomaticPrintA4Delegate. This method switches to the UI thread with
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(AutomaticPrintA4Delegate));
So the print out is running in the UI thread and that is the reason, why your UI is "hanging".
This is my first post here, but I've using this site regularly to help me with my own app's, and I should say that this site has been a great help to me, so thanks to everyone.
Now my question:
I'm developing my first software app that exchanges data between a sql server and the app itself. It's beeing developed in C#. Saving or retreiving data from the sql server database is no problem.
What I want is a way to inform the user of the delay between the local machine (where the app is installed) and the server. I can make some animations or simply display some text messages. What I need help with is how to create the code that activates/fires/runs when that server communication time is running.
If you can't understand the idea, picture a video game. When it's loading (in some games) you can see the loading screen before the game starts. I need some code that displays that "loading window" when the the app is downloading or uploading data from/to the server.
I would appreciate any code example or web site recommendation.
PS: Sorry for the extensive text, but I want to make sure everyone understand so I don't have to repeat it again :P
How do I implement a progress bar in C#?
How to create a smooth progress bar in Visual C#
ProgressBar Class
I have developed a simple PleaseWait class 2 years ago, but I didn't update this class, It works very well, have look hope this will give you an idea to implement your logic.
public partial class frmWait : Form
{
public frmWait()
{
InitializeComponent();
}
bool _isMoving = false;
int _moveStart_x = 0;
int _moveStart_y = 0;
private void tmrProgress_Tick(object sender, EventArgs e)
{
if (barProgress.Value == barProgress.Maximum)
barProgress.Value = barProgress.Minimum;
else
barProgress.Value += 1;
}
private void btnCancel_Click(object sender, EventArgs e)
{
Close();
PleaseWait.Abort();
}
protected override CreateParams CreateParams
{
get
{
System.Windows.Forms.CreateParams p = base.CreateParams;
p.ClassStyle += 0x20000;
p.ExStyle += 0x8000000;
return p;
}
}
protected override void WndProc(ref Message m)
{
const int WM_NCHITTEST = 132;
base.WndProc(ref m);
switch (m.Msg)
{
case WM_NCHITTEST:
if (m.Result.ToInt32() == 1)
m.Result = new IntPtr(2);
break;
}
}
private void panelEx1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_isMoving = true;
_moveStart_x = e.X;
_moveStart_y = e.Y;
}
}
private void panelEx1_MouseUp(object sender, MouseEventArgs e)
{
_isMoving = false;
}
private void pnlContainer_MouseMove(object sender, MouseEventArgs e)
{
if (_isMoving)
this.Location = new Point(Location.X + e.X - _moveStart_x, Location.Y + e.Y - _moveStart_y);
}
}
public class PleaseWait
{
#region Static Operations
private static Boolean _isAborted = false;
private static Boolean _isVisible = false;
private static frmWait _waitForm;
private static String _waitingState = "";
private static Boolean _autoClose = false;
private static Boolean _cancelable = false;
private static System.Threading.Thread _waiterThred;
public delegate void CancelButtonPressed();
public static event CancelButtonPressed OnCancel;
public static Boolean AutoClose
{
get { return PleaseWait._autoClose; }
set { PleaseWait._autoClose = value; }
}
public static string WaitingState
{
get { return PleaseWait._waitingState; }
set { PleaseWait._waitingState = value; }
}
public static bool IsVisible
{
get { return _isVisible; }
internal set { _isVisible = value; }
}
public static void ShowPleaseWait()
{
ShowPleaseWait("", _autoClose, false);
}
public static void ShowPleaseWait(string waitingState)
{
ShowPleaseWait(waitingState, _autoClose, false);
}
public static void ShowPleaseWait(bool autoClose)
{
ShowPleaseWait("", autoClose, false);
}
public static void ShowPleaseWait(string waitingState, bool autoClose, bool cancelable)
{
if (_waiterThred != null)
{
if (_isVisible)
{
// the please wait it woking, just continue and apply the changes
_waitingState = waitingState;
_autoClose = autoClose;
_cancelable = cancelable;
return;
}
else
{
_waiterThred.Abort();
_waiterThred = null;
}
}
_waitingState = waitingState;
_autoClose = autoClose;
_cancelable = cancelable;
_isAborted = false;
_isVisible = false;
if (_autoClose)
Application.Idle += new EventHandler(Application_Idle);
_waiterThred = new System.Threading.Thread(DisplayWaitingForm);
_waiterThred.IsBackground = true;
_waiterThred.Name = "Please Wait....";
_waiterThred.Start();
Application.DoEvents();
}
public static void Abort()
{
_isAborted = true;
}
private static void Application_Idle(object sender, EventArgs e)
{
if (_autoClose)
_isAborted = true;
}
private static void DisplayWaitingForm()
{
if (_waitForm != null)
{
if (!_waitForm.IsDisposed)
_waitForm.Dispose();
_waitForm = null;
_isVisible = false;
}
try
{
if (_isAborted)
return;
_waitForm = new frmWait();
if (_cancelable)
{
_waitForm.btnCancel.Enabled = true;
_waitForm.btnCancel.Click += new EventHandler(btnCancel_Click);
}
try
{
_isVisible = true;
_waitForm.Show();
_waitForm.Focus();
while (!_isAborted)
{
System.Threading.Thread.Sleep(15);
_waitForm.lblMessage.Text = _waitingState;
Application.DoEvents();
_waitForm.lblMessage.Text = _waitingState;
}
_isVisible = false;
}
finally
{
FreeWaitingForm();
}
}
finally
{
_isVisible = false;
}
}
static void btnCancel_Click(object sender, EventArgs e)
{
if (_waitForm.InvokeRequired)
{
_waitForm.BeginInvoke(new EventHandler(btnCancel_Click), new object[] { e });
}
else
{
if (OnCancel != null)
OnCancel.Invoke();
}
}
private static void FreeWaitingForm()
{
_waitingState = "";
_isVisible = false;
if (_waitForm == null)
{
return;
}
_waitForm.Hide();
if (!_waitForm.IsDisposed)
_waitForm.Dispose();
_waitForm = null;
}
#endregion
}
use like following code :
PleaseWait.ShowPleaseWait("Please wait", true, false);
// If second param is true then it will close the form automatically.
// If third param is true the it will expose a cancel button, so you can cancel your Asynchronous operations.
I didn't insert design code, you can understand by looking at code.
hope this help.
First let me thank you for your replies.
Toby your answer got me thinking about thread monitoring my sql connections but it was a bit tricky and confusing since the app is still in develop and will use a lot more connections.
S.Amani answer it wasn't quite what I want, but thanks to that I found a easier way. I created a form (could be anything else), placed a label saying: Saving To Data Base, took out the top bar, defined location and defined it's parent to be disabled when shown and enabled when closed. The following code is what I put inside my DataBaseInteractionClass
private Wait myCustomWaitDialog = new Wait(); // My Waiting form
private void SaveToDatabase(myObjectToSave obj) // Method called to save data do DB
{
// Create the connections and queries
(...)
// This is what I did
// Show Waiting Form
myCustomWaitDialog.Show();
// Instanciate the command that will carry the query and to DB
SqlCommand command = new SqlCommand(Queries.GetData(code), conn);
// This is important
//Create event that will fire when the command completes
command.StatementCompleted += new StatementCompletedEventHandler(command_StatementCompleted);
// Execute the transaction
SqlDataReader reader = command.ExecuteReader();
// Rest of the code (validations, close connections, try/catch, etc
(...)
}
void command_StatementCompleted(object sender, StatementCompletedEventArgs e)
{
// This is the method that closes my Waiting Dialog
myCustomWaitDialog.CloseDialog();
myCustomWaitDialog.Dispose();
}
It's not quite what I want yet, but is the best solution that I found so far. For now it will do :)
Anyway, thanks for the replies and I hope this helps someone else.