Add another "=" to your condition.
one = sign is assignment, you can't do that in the if () condition.
two = signs is used to compare.
You should use:
if (this.LblANDa.Text == "1")
instead.
:)
Add another "=" to your condition.
one = sign is assignment, you can't do that in the if () condition.
two = signs is used to compare.
You should use:
if (this.LblANDa.Text == "1")
instead.
:)
Hmmm...that's odd.
I would say that the values are probably being loaded incorrectly OR they are loaded correctly and it's reporting correctly, just the text file is setup wrong.
The hex value of 128 is 80, I wonder if the hex text file uses FF00 or something goofy.
Could you maybe attach your hex file and the methods that you use to read the text file, load the values into an array and the method you use to get the value of an item in the array?
Add the [Serializable] flag to your ClassMoveToSerialize class if you haven't already.
Also, what exception are you getting?
If you have divided your application up you can create a new solution that is a custom updater. Add the project(s) that you need to update to that solution as well and then all you would need to do is have your updater do a few things:
1. check to make sure the program isn't running
2. find out where the file is that needs to be updated
3. delete the old file (or mark it with the .old extension in case the update fails)
4. copy the new updated file to the same location as the old one
5. clean up any old files and close the updater
It sounds easier than it is, but it's not really that hard either.
If your application is only one file though (a .exe) and no dlls or supporting files, you just need to re-release it because technically that's the update.
Patching is different than updating, but are kinda the same result. Patching is way over my head though. But it can be done, I think there's a way to make installer files that only patch existing installations, but I'm not sure how to do it.
Not 100% sure, but I think you can also just create a report file and send the text to the report and print it that way?
Eh just realized you need to clear the combobox if you run it twice...easy fix...just wanted to point it out
EDIT: Product field should be called Quotient to be accurate. Sorry for any confusion there :)
No, || wouldn't work for absolute value in C#, I believe it's Math.Abs(x);
MSDN: Math.Abs Method (Decimal)
Like I said though, about listing possibilities...whatever you want is fine, but you need some kind of limiter otherwise the computer will loop infinitely.
Here's some code to show what I would do (it's rough, no promises):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace ResolutionCalculator
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int[] GetRatio(int val1, int val2)
{
//find the difference
int Difference = val1 - val2;
//get the abs value
int AbsDifference = Math.Abs(Difference);
//find the first ratio number
int Val1Ratio = val1 / AbsDifference;
//find the second ratio number
int Val2Ratio = val2 / AbsDifference;
//write the ratio to the label
labelRatio.Text = Val1Ratio.ToString() + ":" + Val2Ratio.ToString();
//return our ratio
int[] Ratio = new int[2];
Ratio[0] = Val1Ratio;
Ratio[1] = Val2Ratio;
return Ratio;
}
private void GetSimilarResolutions()
{
//our limiter
int i = 0;
//our maximum iterations
int Iterations = 5;
//our first value
int val1 = int.Parse(maskedTextBoxLength.Text);
//our second value
int val2 = int.Parse(maskedTextBoxWidth.Text);
//our ratio
int[] Ratio = GetRatio(val1, val2);
//the last value of the length
int LastLength = val1;
//the last value of the width
int LastWidth = val2;
//the string to hold a resolution
string Resolution; …
I would imagine the first thing you would need to do is figure out what the ratio is.
Determining ratios is easy, its basically the percentage of each other. Here's an example:
Back in the days of XVGA and SVGA screen resolutions were usually close to the standard 800 x 600. This is a ratio of 4:3. What that means is, for every 4 units of measure in width, there are 3 of the same units of measure in length.
Some people might say that a ratio is a fraction...that's true, kinda. When talking about a 2 dimensional plane (length and width ONLY or only 2 objects) then it can be thought of that way. But if you had a ratio of 4:3:1 or something, that's different.
Here is how you find a 2D ratio (which is probably what you want):
using 800 x 600 as the example. First we find the absolute value of the different between the two numbers, in this case 200. We then divide each by that number:
|(800-600)| = 200
800/200 = 4
600/200 = 3
4:3 is your ratio for 800 x 600.
Here's another example:
1024 x 768:
|(1024-768)| = 256
1024/256 = 4
768/256 = 3
4:3 is the ratio again.
so that means if 800 x 600 and 1024 x 768 have the same ratio, if you increase 800 and 600 and respect the ratio, …
Meh, you lost me...it's really not important at the moment I guess. It was more of a curiosity thing.
Thanks for trying to explain it :)
I see now.
I'm assuming then that the "commands" that have no function to call, only the keyword is set...the "command" that is performed when that keyword is used is generated by Lexer, and not the programmer?
I guess what I mean is, when the command "ADD" is sent (from the example above), the code that is executed is generated by Lexer, not the programmer that created the COMMANDS array? Though I guess they COULD be the same person, but...it's something external is what I'm getting at.
Is that right?
digitig,
Is "lexer" something that is supposed to be common knowledge that I am oblivious to? What I mean is, is it something specific to this application or is it a function of some sort, a website, service...something?
I'm not necessarily trying to learn C/C++, my current project is in C# and that's where it will remain until it is finished, maybe after I'll consider learning C/C++.
The reason I was even looking at this code was to find out how the SQL server processed commands from clients...and even now, after hours of reading, browsing (literally) thousands of files and consuming more aspirin than should legally be allowed I still don't know how it's done.
Hmm...I don't get how they are constructing it then.
In the example above, the first code snippet on line 2 they set that value to "com_help" and then on line 6 and on it is set to "0"
I understand now that it's a delegate, but I don't get how you can set that field to either a string (which I'm assuming points to the name of the function to call) or to an integer. I understand that the function is supposed to return an integer, but I wasn't aware that you could just skip calling a function and just return 0.
Maybe I don't fully understand.
I must say, as a side note, and no offense to anyone who may have contributed, but that source code has got to be the most disorganized mess I've ever read. I got the biggest headache just trying to locate references. But then again I'm not a C++ programmer so meh.
Disclaimer: First, I'm aware that this is C++ code and this is a C# forum, I'm not all that familiar with C++ and was hoping someone here could explain the example below in C#.
I was browsing the very complex source code of the open source project MySQL and saw this bit of code (see attachment for full file, original extension was cc, not cpp):
/* A structure which contains information on the commands this program
can understand. */
typedef struct {
const char *name; /* User printable name of the function. */
char cmd_char; /* msql command character */
int (*func)(String *str,char *); /* Function to call to do the job. */
bool takes_params; /* Max parameters for command */
const char *doc; /* Documentation for this function. */
} COMMANDS;
I understand everything except for line 7:
int (*func)(String *str,char *); /* Function to call to do the job. */
The code moves on immediately after in this type of fashion:
static COMMANDS commands[] = {
{ "?", '?', com_help, 1, "Synonym for `help'." },
{ "clear", 'c', com_clear, 0, "Clear command."},
{ "connect",'r', com_connect,1,
/* SNIPPED FOR BREVITY */
{ "lock tables", 0, 0, 0, ""},
{ "unlock tables", 0, 0, 0, ""},
/* generated 2006-12-28. Refresh occasionally from lexer. */
{ "ACTION", 0, 0, 0, ""},
{ "ADD", 0, 0, 0, ""},
{ "AFTER", 0, 0, 0, ""},
{ "AGAINST", 0, 0, 0, ""},
{ "AGGREGATE", 0, 0, 0, ""},
{ "ALL", …
/* Copyright (C) 2000-2008 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* mysql command tool
* Commands compatible with mSQL by David J. Hughes
*
* Written by:
* Michael 'Monty' Widenius
* Andi Gutmans <andi@zend.com>
* Zeev Suraski <zeev@zend.com>
* Jani Tolonen <jani@mysql.com>
* Matt Wagner <matt@mysql.com>
* Jeremy Cole <jcole@mysql.com>
* Tonu Samuel <tonu@mysql.com>
* Harrison Fisk <harrison@mysql.com>
*
**/
#include "client_priv.h"
#include <m_ctype.h>
#include <stdarg.h>
#include <my_dir.h>
#ifndef __GNU_LIBRARY__
#define __GNU_LIBRARY__ // Skip warnings in getopt.h
#endif
#include "my_readline.h"
#include <signal.h>
#include <violite.h>
#if defined(USE_LIBEDIT_INTERFACE) && defined(HAVE_LOCALE_H)
#include <locale.h>
#endif
const char *VER= "14.15";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
/* Buffer to hold 'version' and 'version_comment' */
static char *server_version= NULL;
/* Array of options to pass to libemysqld */
#define MAX_SERVER_ARGS 64
void* sql_alloc(unsigned size); // Don't use mysqld alloc for these
void sql_element_free(void *ptr);
#include "sql_string.h"
extern "C" {
#if defined(HAVE_CURSES_H) && defined(HAVE_TERM_H)
#include <curses.h>
#include <term.h>
#else
#if defined(HAVE_TERMIOS_H)
#include <termios.h>
#include <unistd.h>
#elif defined(HAVE_TERMBITS_H)
#include <termbits.h>
#elif defined(HAVE_ASM_TERMBITS_H) && (!defined __GLIBC__ || !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ > 0))
#include <asm/termbits.h> // Standard linux
#endif
#undef VOID
#if defined(HAVE_TERMCAP_H)
#include <termcap.h>
#else
#ifdef HAVE_CURSES_H
#include <curses.h>
#endif
#undef SYSV // hack to avoid syntax error
#ifdef HAVE_TERM_H
#include <term.h>
#endif
#endif
#endif
#undef bcmp // Fix problem with new readline
#if defined( __WIN__)
#include <conio.h>
#elif !defined(__NETWARE__)
#include <readline/readline.h>
#define HAVE_READLINE
#endif
//int vidattr(long unsigned int attrs); // Was missing in sun curses
}
#if !defined(HAVE_VIDATTR)
#undef vidattr
#define vidattr(A) {} // Can't get this to work
#endif
#ifdef FN_NO_CASE_SENCE
#define cmp_database(cs,A,B) my_strcasecmp((cs), (A), (B))
#else
#define cmp_database(cs,A,B) strcmp((A),(B))
#endif
#if !defined( __WIN__) && !defined(__NETWARE__) && !defined(THREAD)
#define USE_POPEN
#endif
#include "completion_hash.h"
#define PROMPT_CHAR '\\'
#define DEFAULT_DELIMITER ";"
#define MAX_BATCH_BUFFER_SIZE (1024L * 1024L)
typedef struct st_status
{
int exit_status;
ulong query_start_line;
char *file_name;
LINE_BUFFER *line_buff;
bool batch,add_to_history;
} STATUS;
static HashTable ht;
static char **defaults_argv;
enum enum_info_type { INFO_INFO,INFO_ERROR,INFO_RESULT};
typedef enum enum_info_type INFO_TYPE;
static MYSQL mysql; /* The connection */
static my_bool ignore_errors=0,wait_flag=0,quick=0,
connected=0,opt_raw_data=0,unbuffered=0,output_tables=0,
opt_rehash=1,skip_updates=0,safe_updates=0,one_database=0,
opt_compress=0, using_opt_local_infile=0,
vertical=0, line_numbers=1, column_names=1,opt_html=0,
opt_xml=0,opt_nopager=1, opt_outfile=0, named_cmds= 0,
tty_password= 0, opt_nobeep=0, opt_reconnect=1,
default_charset_used= 0, opt_secure_auth= 0,
default_pager_set= 0, opt_sigint_ignore= 0,
auto_vertical_output= 0,
show_warnings= 0, executing_query= 0, interrupted_query= 0;
static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error;
static my_bool column_types_flag;
static my_bool preserve_comments= 0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
static uint my_end_arg;
static char * opt_mysql_unix_port=0;
static int connect_flag=CLIENT_INTERACTIVE;
static char *current_host,*current_db,*current_user=0,*opt_password=0,
*current_prompt=0, *delimiter_str= 0,
*default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
static char *histfile;
static char *histfile_tmp;
static String glob_buffer,old_buffer;
static String processed_prompt;
static char *full_username=0,*part_username=0,*default_prompt=0;
static int wait_time = 5;
static STATUS status;
static ulong select_limit,max_join_size,opt_connect_timeout=0;
static char mysql_charsets_dir[FN_REFLEN+1];
static const char *xmlmeta[] = {
"&", "&",
"<", "<",
">", ">",
"\"", """,
0, 0
};
static const char *day_names[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
static const char *month_names[]={"Jan","Feb","Mar","Apr","May","Jun","Jul",
"Aug","Sep","Oct","Nov","Dec"};
static char default_pager[FN_REFLEN];
static char pager[FN_REFLEN], outfile[FN_REFLEN];
static FILE *PAGER, *OUTFILE;
static MEM_ROOT hash_mem_root;
static uint prompt_counter;
static char delimiter[16]= DEFAULT_DELIMITER;
static uint delimiter_length= 1;
unsigned short terminal_width= 80;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
#endif
static uint opt_protocol=0;
static CHARSET_INFO *charset_info= &my_charset_latin1;
#include "sslopt-vars.h"
const char *default_dbug_option="d:t:o,/tmp/mysql.trace";
void tee_fprintf(FILE *file, const char *fmt, ...);
void tee_fputs(const char *s, FILE *file);
void tee_puts(const char *s, FILE *file);
void tee_putc(int c, FILE *file);
static void tee_print_sized_data(const char *, unsigned int, unsigned int, bool);
/* The names of functions that actually do the manipulation. */
static int get_options(int argc,char **argv);
extern "C" my_bool get_one_option(int optid, const struct my_option *opt,
char *argument);
static int com_quit(String *str,char*),
com_go(String *str,char*), com_ego(String *str,char*),
com_print(String *str,char*),
com_help(String *str,char*), com_clear(String *str,char*),
com_connect(String *str,char*), com_status(String *str,char*),
com_use(String *str,char*), com_source(String *str, char*),
com_rehash(String *str, char*), com_tee(String *str, char*),
com_notee(String *str, char*), com_charset(String *str,char*),
com_prompt(String *str, char*), com_delimiter(String *str, char*),
com_warnings(String *str, char*), com_nowarnings(String *str, char*);
#ifdef USE_POPEN
static int com_nopager(String *str, char*), com_pager(String *str, char*),
com_edit(String *str,char*), com_shell(String *str, char *);
#endif
static int read_and_execute(bool interactive);
static int sql_connect(char *host,char *database,char *user,char *password,
uint silent);
static const char *server_version_string(MYSQL *mysql);
static int put_info(const char *str,INFO_TYPE info,uint error=0,
const char *sql_state=0);
static int put_error(MYSQL *mysql);
static void safe_put_field(const char *pos,ulong length);
static void xmlencode_print(const char *src, uint length);
static void init_pager();
static void end_pager();
static void init_tee(const char *);
static void end_tee();
static const char* construct_prompt();
static char *get_arg(char *line, my_bool get_next_arg);
static void init_username();
static void add_int_to_prompt(int toadd);
static int get_result_width(MYSQL_RES *res);
static int get_field_disp_length(MYSQL_FIELD * field);
/* A structure which contains information on the commands this program
can understand. */
typedef struct {
const char *name; /* User printable name of the function. */
char cmd_char; /* msql command character */
int (*func)(String *str,char *); /* Function to call to do the job. */
bool takes_params; /* Max parameters for command */
const char *doc; /* Documentation for this function. */
} COMMANDS;
static COMMANDS commands[] = {
{ "?", '?', com_help, 1, "Synonym for `help'." },
{ "clear", 'c', com_clear, 0, "Clear command."},
{ "connect",'r', com_connect,1,
"Reconnect to the server. Optional arguments are db and host." },
{ "delimiter", 'd', com_delimiter, 1,
"Set statement delimiter." },
#ifdef USE_POPEN
{ "edit", 'e', com_edit, 0, "Edit command with $EDITOR."},
#endif
{ "ego", 'G', com_ego, 0,
"Send command to mysql server, display result vertically."},
{ "exit", 'q', com_quit, 0, "Exit mysql. Same as quit."},
{ "go", 'g', com_go, 0, "Send command to mysql server." },
{ "help", 'h', com_help, 1, "Display this help." },
#ifdef USE_POPEN
{ "nopager",'n', com_nopager,0, "Disable pager, print to stdout." },
#endif
{ "notee", 't', com_notee, 0, "Don't write into outfile." },
#ifdef USE_POPEN
{ "pager", 'P', com_pager, 1,
"Set PAGER [to_pager]. Print the query results via PAGER." },
#endif
{ "print", 'p', com_print, 0, "Print current command." },
{ "prompt", 'R', com_prompt, 1, "Change your mysql prompt."},
{ "quit", 'q', com_quit, 0, "Quit mysql." },
{ "rehash", '#', com_rehash, 0, "Rebuild completion hash." },
{ "source", '.', com_source, 1,
"Execute an SQL script file. Takes a file name as an argument."},
{ "status", 's', com_status, 0, "Get status information from the server."},
#ifdef USE_POPEN
{ "system", '!', com_shell, 1, "Execute a system shell command."},
#endif
{ "tee", 'T', com_tee, 1,
"Set outfile [to_outfile]. Append everything into given outfile." },
{ "use", 'u', com_use, 1,
"Use another database. Takes database name as argument." },
{ "charset", 'C', com_charset, 1,
"Switch to another
Hmmm...
I'll have to re-read your post after I've had more coffee. I think I gather what you are saying, and it sounds similar to what I am already doing (or had in mind I suppose).
Thanks for the help! Would you, if you have time of course, post a "shell" of the concept? Some code that I can cypher through just to illustrate and better understand the idea. I would appreciate it greatly! :)
I've been struggling with this for a while.
It's not so much a "problem" as it is an approach. I've been working on my client/server socket program and I've reached the point in my planning (which isn't very far in) where I really need to think about how the server will receive commands and respond to them.
Since the server is going to be accepting commands from network clients, interpreting them and (if necessary) running a query on a local SQL server and returning the results to the client the idea of string based commands is not optimal in my opinion, serialized objects sound better.
I was hoping someone could take a minute and give me some feedback on how I plan to approach this.
I know that protocols are all different, and I'm not really asking for that, I have that, but the actual data being transmitted is where I'm stuck.
My idea currently is to have one class for each command type (get data, save data, update data, delete data etc...) and each class would be publicly accessible to both the server and the client. The advantage to this is that the class would only contain data needed to perform that specific task, updating for example would contain a string that held a catalog name, an integer for the row to update or maybe just a datarow and the catalog name. The command type could be transmitted with the object over the socket …
That's true. However, in this sitution, setting that field value to "false" is supposed to affect all instances of the class, and all associated threads.
Ahhhhhhh
I see what you are saying now! And yes, that is the intention, if the Status field holds a bool value indicating "true" if the server is "running," setting it to "false" would correctly break all of the threads in a "connection loop" out, so they can close the socket and end gracefully. Aborting the thread is dirty, and bleh...I don't even want to think about it.
You wouldn't want to use a static lock with a non-static object. Remember that all objects of that type will be locked when one thread tries to access them.
Wait a second. What?
I must have missed something. Objects of what type will be locked? Are they locked automatically? If that's true...oh my, the time I've spent agonizing over thread safety for objects that may, or may not need to be locked!
minitech,
Thanks for the insight. It's for a socket server listening loop. Closing the socket will end the listening thread correctly, so I'll just do that, but it just got me thinking of ways to do it gracefully, never used it before, but was curious about it if I ever needed to use it.
Quick question:
Is this valid, or am I missing a potential deadlock in the future:
static readonly object _LockThis = new object();
private static bool _Status;
private bool Status
{
get { lock (_LockThis) { return _Status; } }
set { lock (_LockThis) { _Status = value; } }
}
private void Work()
{
while (Status)
{
//do some work
}
}
private void StopWorking()
{
Status = false;
}
private void StartWorking()
{
Status = true;
Thread WorkThread = new Thread(Work);
WorkThread.Start();
StopWorking();
}
Excellent point. My brain immediately thought "thread ends, socket closes" but that's not true.
I think the service controller aborts the service thread after 30 seconds doesn't it? When it receives the stop command I mean.
Guess it's best to try to close all threads, close all sockets and hope it finishes in 30 seconds. If not, doesn't really matter, the ports will stay open anyway until they timeout.
Any consensus?
I see advantages and disadvantages to both.
For a socket listener, a background thread would be good I would imagine, if the server is attempting to close, it obviously does not need or want to accept connections and any connection that is in the process of starting should stop...immediately.
For a connected socket, my opinions vary. Background is good so that if a server is closing and has hundreds of threads (potentially) ending them all gracefully could take time, and if the server is running as a service, this could cause the service controller to have a fit because the service didn't end fast enough, but background threads would just stop. But it also causes havoc for the client(s) connected (maybe) and they wouldn't receive notification that the connection died until it timed out or a check was made by the client...
Anyone have any thoughts or opinions?
Great! Glad it was helpful!
Thought so.
Thanks!
Ooooh I like it!
Excellent idea! Thanks!
But still, my curiosity has the best of me...would that be a cross-process signal or did I miss something?
I have the dll source. It's a project in my solution. Would this still be a preferred way? I can modify the dll, it's not a third party file :)
Remember the server I was working on...remember I was going to have a "server core?" That server core is the dll I'm talking about. I have a button on my management form that allows the user to start the server. I would like that button click to create a new thread and run the "StartServer()" method on the dll. But I want to make sure that the server has completed starting before moving on.
Well, I would say there are two steps involved here.
You will probably (for clarity in my opinion) need two methods, one for each of those tasks.
For the first step I would check out the Drawing namespace. You need a method that returns a Bitmap object first. You can add the text from your textbox to the bitmap with the Graphics.Drawstring method. There's a (somewhat) decent example of this being done here.
For the second step, you need to modify your new bitmap object. This is the tricky part. I would suggest you start here.
I've never done anything like what you are doing though. Those are good starting points though.
Try searching Google for "Image Processing in C#" also for more ideas with the second step.
Those are just my suggestions, someone might have better ones.
No no no...let me clarify.
Say thread1 starts running and something happens and it needs to spawn off a new thread, but after it spawns it off it calls WaitOne() and waits for the thread it started to call Set()
For example...
CountdownEvent ThreadSignaler = new CountdownEvent(1);
private void InspectEnvironment()
{
Action SignalDone;
//initialize a thread to check for sql servers
Thread FindSqlServersThread = new Thread(FindSqlServers);
FindSqlServersThread.Name = "Find SQL Servers Thread";
//start the threads
FindSqlServersThread.Start();
ThreadSignaler.Wait(); //wait for the FindSqlServersThread to finish.
//continue working...
}
#region Threaded
private void FindSqlServers()
{
//Simulate some boring task
Thread.Sleep(3000);
//The thread is tired of living, and commits suicide
ThreadSignaler.Signal(1);
}
This code works wonderfully! But they are both in the same class, and same namespace.
Assume for a moment that "FindSqlServers()" is NOT located in the same class or namespace, but is actually located in an external dll file that is only referenced. I can't call ThreadSignaler.Signal(1); in the dll because ThreadSignaler doesn't exist in the dll, and if I create it, wouldn't it be a different instance of the wait handle? It seems like it would be signaling the wrong one unless I use a cross-process signal?
So...you want to take text from the box and turn it into a graphical representation with noise in it?
Or do you want to have an image appear and have the user enter what they see?
*shutters* ...homework
evilmarksman,
Not sure I understand what you need to do. Where are you getting the data from? Do you enter it or retrieve it from some file or server source?
If I start a new thread, and that thread executes a method that is contained in a referenced dll, how do they signal each other? Would this be considered a cross-process EventWaitHandle? It doesn't seem like it would be considering that the thread is started in the same process. I always pictured a "cross-process" as two separate executables that signal each other, but maybe it applies to references as well? I can't seem to figure this one out. Any suggestions would be great!
Hmmm...excellent points.
I might have to think about this a bit more.
Momerath,
Yes, I do want to limit the number of connections.
It's not for "software" limitation per-se...I'm not going to have X, Y, and Z versions of the software, each with a different connection limit, I hate that. I want to allow my users the ability to control the number of connections permitted to the server. I want to do this for a few reasons:
1. extra (though small) amount of security - Unlimited (or limited by system resources) connections allow for would be trouble makers to connect to the server (or at least try to anyway) hundreds of thousands of times with the intention of slowing down or even "killing" the hosting machine.
2. to allow the server administrators the ability to control resources better - while it may seem silly, some people may not have very good hardware and some "throttling" might be in order, limiting the number of connections could help with that.
3. selling point - control (no matter how small) gives the perception of power. Lets be honest, software that has more things to "tinker" with are great selling points so long as the default values are sufficient for those who don't like to tinker.
Is anyone aware of a way to do this?
I considered adding a while statement to the listening loop of the server to evaluate if an integer is >= a certain value, and if so to enter another loop until it's not true, and that would allow the server to accept more connections. The server would increment or decrement the integer each time a connection is opened/closed. Seems a little heavy though. Is there a method built into Sockets that can allow me to set a maximum number of connections?
Any suggestions would be greatly appreciated.
Not sure, could you post some of your source code? Specifically portions that read and send the file, and also the portions that receive and write the file.
Any time :)
Might I suggest you use a MDI form? It would make getting that list very easy.
As for finding the last active form, try the Activated event instead of LostFocus and GotFocus.
From MSDN:
The Enter and Leave events are suppressed by the Form class. The equivalent events in the Form class are the Activated and Deactivate events. The Enter and Leave events are hierarchical and will cascade up and down the parent chain until the appropriate control is reached. For example, assume you have a Form with two GroupBox controls, and each GroupBox control has one TextBox control. When the caret is moved from one TextBox to the other, the Leave event is raised for the TextBox and GroupBox, and the Enter event is raised for the other GroupBox and TextBox.
For your reading pleasure:
Activated
Deactiveate
True.
Maybe a queue would work best, and the server core can just check a flag to see if there are commands pending and execute them as needed.
This should be interesting... *holds an envelope to his head* hmmm...I see great problems in my future...
Yes, it's going to fall apart. By having just one connection to the database like this it's possible for multiple threads to place the connection in various states, interrupt threads that are trying to read/write the database, etc.
Create a new connection for each thread. The way the .NET database code is designed it already allocates ten connection threads (I believe it's 10, could be 20) automatically (you don't have access to them directly, it does the assigning behind the scene as you create new connection objects).
Thread safe database code can be very tricky, as you need to ensure that no one is doing an update when one thread is doing an update, no one is reading when you are updating, etc. Some of this the database can handle but you do need to keep it in mind as you code.
Momerath,
Maybe I explained it poorly. Let me try to clarify a bit.
There are three parts here:
Server Manager - An executable that presents a user interface for the server.
Server Core - A dll file that contains methods and information on how clients can communicate with the server (the protocols, the available commands etc...)
SQL Server - this stores the data, and is ONLY accessed by the methods in the Server Core.
When the user clicks the button to start the server on the form it creates a new thread, and on that thread it executes a method contained in the Server Core …
I don't know how to title this thread, forgive me if it's bad.
I'm trying to determine the best way of handling this and I'm getting nervous about it.
The basic setup I have is a server system that is run when the application is open (it's not a service, but a winforms app). The server form shows (among other things) a button to start and stop the server, and a rich text box showing the activity of the server and the clients connected to it.
Standard modeling for something like this (I think) suggests 3 layers. A UX layer(or GUI layer for you old farts), a logic layer (the methods used to interact with the data...the core of the server really), and the data layer (in this case a SQL server).
In my situation, the UX is a win form app, the logic is a dll which bridges the UX layer to the data layer.
Since each connection to the server will run on its own thread, what is the best way for those threaded connection instances to access the logic layer to update, delete, get data etc...basically "talk" to the server? I was going to put on my UX form a static instance of the logic layer (the dll) and just have the threads use that, but I'm worried that if I do that, the UX layer will "hang" while methods are called from it. That can't happen.
So I guess the …
nutrion,
Threads are actually quite simple when you get the hang of it. Momerath's example is a great place to start.
One of the best resources I ever found on threads is available for free online, and has earned a permanent tab on my Chrome taskbar that never closes. You can read it here: http://www.albahari.com/threading/ It's lengthy, but well worth the read.
Basically threads can be thought of as "children" to a degree. They spawn from a point and die after they are done living. The thing with delegates is that if you have two children and both of them want the same piece of candy, they end up fighting over it. That's why locks are used, and delegates.
Here's a simple example I've used. The code spawns from the main GUI thread and changes an image in a picturebox when a certain outcome is achieved. The example shows 3 threads total (which is not necessary but done for example only) One is the main GUI thread, one is a thread that is spawned by the GUI thread which spawns two more threads and waits for them to complete before continuing:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Microsoft.Win32;
using System.ServiceProcess;
using System.Data.Sql;
namespace DATA.Wizards.FirstRun
{
public partial class Step1 : Form
{
//initialize access to the Wizard Controller
Start WizardController;
public Step1(Start wizardController)
{
InitializeComponent();
WizardController = wizardController;
}
// …
Is a timer on the main thread necessary?
If I only start a thread in the OnStart() method, will the mere existence of the thread I started indicate that the service is running?
What happens if I leave OnStart empty and don't start a thread? Is it possible to just have the service sit idle until a custom command is issued that starts the work?
Okay, so...where is the main thread at?
Looking at MSDN here it only mentions OnStart, OnPause, OnStop, OnContinue, OnShutdown, OnCustomCommand, OnPowerEvent...that's great...but what about the work or main method? I don't see it.
It does mention the Run method that is in the Main method, but looking here that Run method in the main method registers the service with the service controller and then the service controller executes the OnStart method and then what? Can I add my code under the call to Run()?
I'm so lost on how it actually works. Can the main method block or loop? Seems like a bad idea, wouldn't that render the service useless if the service controller tried talking to it or stopping it? It seems like from what I have read you have two choices when coding a service:
1. Create a timer and make your service execute a command on a set interval
2. Sprout off a thread (or threads) and run your code there.
Seems silly to me if those are the only options. I mean, a service that monitors a port or something for a connection request has to block (to be efficient it does anyway) and if that's the case, blocking a main thread seems like a terrible idea. At the very least 2 threads need to be used, one that blocks and one that listens to the service controller.
Am I missing something?
Glad it was helpful :)
Ouch...good point.
Quick (really) question about windows services.
According to the documentation, services require a minimum of 2 methods OnStart() and OnStop() to be useful.
OnStart() cannot contain the main execution code, it shouldn't loop, block or otherwise prevent the OnStart() method from returning quickly.
The Question:
If the above is true...it seems like, for a service to have any use at all, the OnStart() method MUST execute a different method on a different thread because running a method on the same thread from within the OnStart() method would cause blocking if that other method looped infinately...OnStart() would never return.
Is that correct?
Also, one other question for bonus points.
If a service implements OnCustomCommand(), you pass the custom command to the Service Controller and the Service Controller tells the service "Hey! do this command" and then ignores the service (doesn't wait for the service to do anything, it's just the messenger).
The question is, when the Service Controller does that, does the simple inclusion of the OnCustomCommand() method automatically listen for those commands? I guess what I mean is, if OnStart() starts a new thread (called ThreadA) and ThreadA runs in an infinite loop or blocks, while ThreadA is sitting there serving up whatever service it's supposed to and looping like there is no tomorrow, the OnStart() method that sprung ThreadA has ended which was on a different thread. Is that original (main) thread gone? Who is the Service Controller talking to? ThreadA? …
Lucky...at least you don't have bosses to deal with...
Hmmm...that's an interesting thought. I'll have to think about that one. I suppose it does make sense.
Thanks! You are always a well of endless good ideas! Who do you work for? Can we steal you? lol