|
I went back to the single thread yesterday, and converted my threads to Await or Async. The part that sends the email is threaded already, using Thread and ThreadStart. I mange to run one test yesterday, and so far so good, it worked. Just need to plug in the sending part and test again.
Right now, the subscriber list has about 4000 people, so with a 5 second pause, it doesn't take long to send the list, about 4 hours. And they all go to the same mailserver for sending.
Well for what its worth, at least I have some experience with it, and will be ready if that day ever comes.
I'll probably be back for the stop question, if the cancellation token doesn't work for shutting down the service, and I need to figure how how to save the position of the subscriber list, to pick up where it left off.
But Thanks for the real work view for the proper design aspect!
|
|
|
|
|
Yup - nothing like learning the hard way!
Do you really need a 5 second pause between mails? Maybe it depends on your mail server/service, but it shouldn't really be necessary. I've sent to lists of c 4,000 in a fraction of the time yours are taking - talking minutes, not hours - using 3 threads in the sending routine.
|
|
|
|
|
The idea behind that was to allow time for other things;
Be nice to the mail server at the customers ISP, instead of bombarding it, just do a slow feed.
Allow time for people using the website to squeeze in a page request.
I was thinking of that Russian search engine Yandex that just goes full force on my web servers, and didn't want to be like that.
I just reread this, your using 3 threads?
I do compress the HTML before sending to make a smaller package.
|
|
|
|
|
Well, you have a different model from me; in my case, I'm hosting the client websites, and my mail program runs as an exe in the background regularly polling their databases to see if they've initiated a mailout. When it finds one, it cycles through their mailing-list/s and sends out their newsletter, using a 3-threaded routine. The emails are sent using a third-party email relay service - my exe simply creates the mail messages and fires them off using this relay service. It's very quick, and doesn't impact on the sites' performance in any noticeable way.
|
|
|
|
|
The email relay sounds like a good idea. I should look into that. I wanted to do the Thread gig so later, I could expand it to pushing out emails faster.
This is for an eCommerce site that I wrote from scratch. All the other emails such as order confirmation and your order has shipped gets called by the main thread, and the worker thread loads the HTML Template, changes the field values, and sends it off. The HTML Template is a HTML Document in the App_Data the operator can change to their liking, so it's not hard coded.
Here's the story:
This post is for the Email Advertising Campaign. i originally wrote it as a web app on the back end of my eCommerce program. But when I upgraded my code to Entity Framework, I could not figure out how to talk to the database. So for Black Friday, I had to write Windows Desktop App really fast to send out the emails. That was my first sales campaign, which produced a ton of sales that weekend.
Then I expanded my program, for another sale, and another, more revenue came in. So I added more programs to match what I had on the back end of my web app. So now you can generate HTML templates to send, publish them, create jobs, send jobs by date, book jobs into the future. It's sort of a Swiss knife Windows Desktop App that does it all.
Then I decided to add the Windows Service that I broke back into the program to send in the background, and eventually put it back into my website to run on the server. So this new windows service kicked my butt in terms of design and security permissions. But I figured out how to make a web service on the website to use for data, and write binary serialization classes to the disk drive with permission for the Windows App and the Windows Service. Thought the treads would be the icing on the cake.
So Today
I'm sending emails now using the web service. Now I just need to write a binary file to the disk drive to store the current position of the job, in case the power goes out, or the computer / server is turned off so the service can resume it's duties. And a Task Bar program.
Your program sounds really cool, and I like the design.
I'm curious, what do you think of this Swiss Knife Windows App that I wrote about?
Think it's a waste of time?
Would you be interested in looking at the instruction manual for it?
The intent was to move the website back end to a windows app, and convert the back end into a simple mobile design for small task from the phone. Experiment with being able to do this without tunneling to the database server or punching holes in the firewall.
|
|
|
|
|
If it works for you, it's good! The only bad program is one that doesn't do the job. And pitifully few programs are (able to be) fully thought and mapped out in advance - the usual story is, as in yours, that we're flying by the seat of our pants doing what we can in the limited amount of time our bosses or clients give us, and having to accommodate their ever-changing requirements into the bargain.
I'll bear your offer in mind, but I really haven't got time right now to devote to looking at it - on top of two or three other non-trivial projects I've just had a whopper land on my desk which I need to get to grips with fast, which means getting my head around writing cross-platform "open" mobile apps - see my post in that forum if you're interested!
|
|
|
|
|
Time!, this stuff is so time consuming to write.
I'll take that as positive feedback, and what ever it takes to make the job easier for the users.
I have to wrap this up today because too much time has been spent on it.
|
|
|
|
|
Hello people,
I have made a CheckedListBox,
now is my issue here is my code
Public Sub SQL_Columns_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
MyCbList.Items.Add("Owner", CheckState.Checked)
MyCbList.Items.Add("Translator", CheckState.Checked)
MyCbList.Items.Add("Order number", CheckState.Checked)
MyCbList.Items.Add("Quotation number", CheckState.Checked)
MyCbList.Items.Add("Area", CheckState.Checked)
MyCbList.Items.Add("Description", CheckState.Checked)
MyCbList.Items.Add("Order date", CheckState.Checked)
MyCbList.Items.Add("Delivery date", CheckState.Checked)
MyCbList.Items.Add("Source langugage", CheckState.Checked)
MyCbList.Items.Add("Target langugage", CheckState.Checked)
MyCbList.Items.Add("No hit", CheckState.Checked)
MyCbList.Items.Add("Words(75-84)", CheckState.Checked)
MyCbList.Items.Add("Words(85-94) ", CheckState.Checked)
MyCbList.Items.Add("Words (95-99)", CheckState.Checked)
MyCbList.Items.Add("Words (100%)", CheckState.Checked)
MyCbList.Items.Add("Words (repetitins)", CheckState.Checked)
MyCbList.Items.Add("Words (CM)", CheckState.Checked)
MyCbList.Items.Add("Words (Total Words)", CheckState.Checked)
MyCbList.Items.Add("DTP", CheckState.Checked)
MyCbList.Items.Add("Ext.hr", CheckState.Checked)
MyCbList.Items.Add("Int.hrs", CheckState.Checked)
MyCbList.Items.Add("Cust. Invoiced", CheckState.Checked)
MyCbList.Items.Add("Estimated Customer Total", CheckState.Checked)
MyCbList.Items.Add("Estimated TB", CheckState.Checked)
End Sub
I wonder how do I make item to a string if the item is checked?
thank you in advance
|
|
|
|
|
This should work in .NET 4.0 or higher:
Dim theCheckedItems As String = String.Join(Environment.NewLine, MyCbList.CheckedItems)
If you're using .NET 3.5, then you'll need to convert the collection to a string array:
Dim theCheckedItems As String = String.Join(Environment.NewLine, MyCbList.CheckedItems.Select(Function(item) Convert.ToString(item)).ToArray())
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
So I have a Windows Form Program that writes a serializable class to a binary file, to store SMTP server information. The goal is to store data that both program can use. One program writes the data and the other program, the service consumes the data.
I tried registry, but since the Windows Form program runs as a user, and not a service account, I can't really access the correct registry key in HKEY_CURRENT_USERS.
So I thought, OK, I'll write the data to a file, so the service can read it. But after hours of trying to learn how to debug OnStart, and finally able to do it, the service can't read the file that the Windows Form app wrote, a security issue; versions don't match.
So now I tried moving the Serializable class to the 3rd program, the web service, and placing it there. Figuring that the 2 program can just use the class in the Service Reference for the Web Service. Only the serializable class won't publish unless I use it in the Web Service.
I read there was a way to use Version1Type, and Version2Type so that several programs can share the data files, but it doesn't seem to exist in System.Runtime.Serialization.
I guess I could write a XML file, but that's a lot of work. I really like the binary data file. But can't figure out how to match the versions. I'm using 4.5
|
|
|
|
|
Serializing to an XML file is a lot of work? On which planet? It's actually really easy to do.
Here[^] and here[^].
Put the classes that you serialize into a 4th project which all of your other projects reference. This will keep the full type name of the classes consistent and the versions won't change as you modify the programs. You can also put the file under the CommonApplicationData (Environment.GetFolderPath) folder for a nice place that every application in this project can get to. It'll resolve to C:\ProgramData. Stick your files in a folder under there.
|
|
|
|
|
I was thinking last night just put the file io and serialization classes in a 4th project DLL, and just have the 2 windows programs reference it.
I was aware of saving the serialized classes as XML, but I was on another planet, looking back at earth after trying to debug the web service. I didn't know it would be that easy to do.
I'll look into changing where I save the files, right now, I saved them in the Program files folder for the project.
I'll give it a spin today and see what happens.
Thanks Dave
|
|
|
|
|
Yeah, everything under Program Files is read-only to users. Not a good place to write data at all.
|
|
|
|
|
I didn't know it was read only, good call on making that comment, thanks!
Now I have 7 projects in my solution. It's getting complicated to just send promotional emails.
But I was able to write the file in the Win app, and read it in the Win Service using the Common DLL that I just wrote. So now I guess I might as well centralized all the shared stuff, to make it easier to update and keep track of, and dump the registry storage for the Binary files. And move the Service Reference to the Common DLL and the Soap calls as well.
Thanks Again Dave!
|
|
|
|
|
I'd recommend using a file-based database, like SQLite. Easiest way to prevent versioning-problems with serialization, is not to use serialization.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
That's a good idea, but I already wrote a Web Service for the web site that the programs access data for. Hard to explain, but the windows programs access a website web service that in turn access the database server for data. The Serialization binary files store the web service location and credentials and the mail server location and credentials.
I was trying to avoid using another database server.
I'll try a 4the project today and integrate common code into it, that both windows programs can use to access common features.
I'll give it a spin right now.
Thanks Eddy!
May be back today.
|
|
|
|
|
jkirkerx wrote: I was trying to avoid using another database server. SQLite, SqlCe and Access aren't servers; with SQLite having a very small footprint and being available on multiple platforms
jkirkerx wrote: I'll give it a spin right now. You're welcome
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
I guess your advice is probably the better advice.
I'll write a general post in my thread.
|
|
|
|
|
So I wrote a commmon DLL and moved all the common stuff over to it.
Now I get a Access Denied from the Folder
c:\ProgramData\redCopper\smtpMessenger\ and not the serialized binary file.
I wrote a text file to the folder, and set the code to open it, got the same error.
I thought in theory, I would be able to write to it from the Windows Form App, which works and read it from the Common DLL, that represents the Windows Service, Which doesn't work.
So I wonder if it's because I had to elevate VS 2013 To Administrator, to debug the Windows Service OnStart Event. The Windows Service runs on Local Account
Dim m_appPath As String = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) & "\redCopper\smtpMessenger\smtpCredentials.bin"
Try
Using fs As New FileStream(m_appPath, FileMode.Open)
Dim bf As New BinaryFormatter()
pResults = bf.Deserialize(fs)
End Using
|
|
|
|
|
Users are, by default, not allowed to write to "ProgramData", only admins. It is an admin that installs the application, and any shared files it needs to read. Data is saved somewhere else; it is not part of the installation-package, and since it cannot be reinstalled, it must be in a location that is backed up regularly.
When running under the users' credentials, it will not be allowed to write there; alternatively, you can write to the "public" documents folder. All users should have access to that one (documents and settings\public\etc).
See this[^] page.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
I see why you suggested the SQ Lite, you had the foresight of knowing I would run into this.
My post time was the end of the day, and I should of done more research on storing data.
I could of sworn that I read that Program files had read write permissions for any program installed in that folder since Vista, but I haven't updated my knowledge since Windows 7.
I'll try Public today and see how that goes.
Thanks Eddy!
|
|
|
|
|
jkirkerx wrote: I see why you suggested the SQ Lite, you had the foresight of knowing I would run into this. Rereading the question I had the feeling we had a similar problem, so yes, been there*. I tend to stick almost everything in a SQLite .dat file, from resources and sprocs to assemblies. Makes stuff easy to copy and mail, makes stuff easy to update. And best of all, there is SQL to separate the data from the rest of the app, so I won't spend much time on writing code for that infrastructure.
jkirkerx wrote: I haven't updated my knowledge since Windows 7. Neither have I, but I will be installing any later stable version that has a good price/value ratio.
*) A few times
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
What a pain in the A??.
I was looking at other windows services loaded on my machine, and noticed a few that used the Windows user account to run as. So I figured I'll give that a try.
Easier said than done. Installing the service as a user with a password was much harder than I thought. So I ended creating a new console app that can run as a Windows service, and used some new stuff out there referred to as a Custom Service Base, Custom Service Installer and IServiceLogic and TransactedInstaller. Pretty slick now. The service can self install and uninstall, can be debugged pretty easy now. In fact its so nice, I should publish an article on it.
So I just performed my i/o test, using the common DLL file that now does all the I/O for both programs, the SOAP calls to the Web Service, And the reading and writing of my serialized class files that store parameters, which is now located in the AppData folder of the user account (LocalApplicationData) and it worked without any errors on all 3 programs. No more folder errors or binary read errors from the creator assembly.
So now, I since I wrote a new service, I might as well trick it out, and make it better and more up to date, guess I'll write some threads that the service can run to do it's gig.
I was smart enough this time to make a copy of the project, in it's sort of raw form that just supports install and uninstall and debug, with no other logic in it.
Thanks Dave and Eddy for the help!
The Link to the Service code that I used
Creating easy to debug Windows Services in .NET - CodeCaster.nl - Blog[^][^]
|
|
|
|
|
I have used two forms and one form open to showdialog condition...
while showdialog closing at the same time need to another form closed...this is my problem so please solve this..........
|
|
|
|
|
On return from ShowDialog you can close the form.
|
|
|
|
|