Thread Vs ParameterizedThreadStart - asp.net

I am newbie in .NET. I am using Threads in my project. please check my code below -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication6
{
class Program
{
private void Amadeus(object str)
{
Console.WriteLine(str.ToString());
}
static void Main(string[] args)
{
Program objClass = new Program();
//One way to call Amadeus Method...
Thread objThread = new Thread(objClass.Amadeus);
objThread.Start("Amadeus without ParameterizedThreadStart");
//Other way to call Amadeus Method...
ParameterizedThreadStart objParamThread = new ParameterizedThreadStart(objClass.Amadeus);
Thread ObjThreadParam = new Thread(objParamThread);
ObjThreadParam.Start("Amadeus with ParameterizedThreadStart");
Console.ReadLine();
}
}
}
Can you please tell me what is the difference between above both way as both are doing same work.
Thanks in advance.

Both are same. Read the MSDN documentation.
Visual Basic and C# users can omit the ThreadStart or
ParameterizedThreadStart delegate constructor when creating a thread.
In Visual Basic, use the AddressOf operator when passing your method
to the Thread constructor; for example, Dim t As New Thread(AddressOf
ThreadProc). In C#, simply specify the name of the thread procedure.
The compiler selects the correct delegate constructor.

Yes, both are doing the same thing.
You can create a thread by passing in a function with a ThreadStart (void ThreadStart()) or ParameterisedThreadStart (void ParameterisedThreadStart(Object x)) signature.
The compiler is working out which constructor to call from the type of parameter you are passing into the constructor.

Related

How do I get ShellSettingsManager in an async extension to VS2019?

I wanted to create a small extension to add a list of External Tools to VS2019. A quick search brought up what appeared to be perfect example code at https://learn.microsoft.com/en-us/visualstudio/extensibility/writing-to-the-user-settings-store?view=vs-2019. This adds a command to invoke Notepad, so I thought with a few edits, my work was done.
However, this example is written as a synchronous extension, which is deprecated, so I tried putting the code intended for MenuItemCallBack into the Execute method of the extension, but the line
SettingsManager settingsManager = new ShellSettingsManager(ServiceProvider);
fails to compile, because ServiceProvider is now type IAsyncServiceProvider and the ShellSettingsManager constructor wants an argument of type IServiceProvider.
As far as I can tell, ShellSettingsManager is still the way to access the Settings Store, but all the examples I could find all refer to putting code in MenuItemCallback (as well as being several years old) so are for synchronous extensions.
So, can someone point me to the recommended way to get access to the settings store in an asynchronous extension?
The ShellSettingsManager constructor takes either an IServiceProvider interface or an IVsSettings interface. Given your AsyncPackage derived object implements IServiceProvider, you should be able to just pass it in as the argument to your constructor. The following quick demo package worked for me:
using System;
using System.ComponentModel.Design;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft;
using Microsoft.VisualStudio.Settings;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Shell.Settings;
using Task = System.Threading.Tasks.Task;
namespace UserSettingsDemo
{
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[Guid(UserSettingsDemoPackage.PackageGuidString)]
[ProvideMenuResource("Menus.ctmenu", 1)]
public sealed class UserSettingsDemoPackage : AsyncPackage
{
public const string PackageGuidString = "cff6cdea-21d1-4736-b5ea-6736624e718f";
public static readonly Guid CommandSet = new Guid("dde1417d-ae0d-46c4-8c84-31883dc1a835");
public const int ListExternalToolsCommand = 0x0100;
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
OleMenuCommandService commandService = await GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
Assumes.Present(commandService);
var menuItem = new MenuCommand(OnListExternalTools, new CommandID(CommandSet, ListExternalToolsCommand));
commandService.AddCommand(menuItem);
}
private void OnListExternalTools(object sender, EventArgs e)
{
ShellSettingsManager settingsManager = new ShellSettingsManager(this);
WritableSettingsStore userSettingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings);
int toolCount = userSettingsStore.GetInt32("External Tools", "ToolNumKeys");
for (int i = 0; i < toolCount; i++)
{
string tool = userSettingsStore.GetString("External Tools", "ToolCmd" + i);
VsShellUtilities.ShowMessageBox(this, tool, "External Tools", OLEMSGICON.OLEMSGICON_INFO,
OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
}
}
}
}
Sincerely

Dapper.Contrib methods unavailable for IDbConnection object

I am trying to use Dapper.Contrib to extend the functionality of the IDbConnection interface with, amongst others, the .insert() method.
To do so, I have followed the somewhat brief and scattered documentation here and here. In short, I have used NuGet to add Dapper and Dapper.Contrib to my project, I have added using Dapper; and using Dapper.Contrib; at the top of my Repository class, and I am using System.Data.SqlClient.SqlConnection() to create an IDbConnection.
Still, my connection object does not have the extended methods available. For example, when trying to use the .insert() method, I get the message:
'IDbConnection' C# does not contain a definition for 'Insert' and no
extension method 'Insert' accepting a first argument of type could be
found (are you missing a using directive or an assembly reference?)
This is in an ASP.NET Core 2.0 project using Razor Pages.
For completeness sake, you can find the Repository class below.
Maybe interesting to note, is that the using lines for Dapper and Dapper.Contrib are grayed out...
Also, of course I have a (very minimalistic) Model Class for the TEST Entity, containing one parameter, TEST_COLUMN, annotated with [Key].
using Dapper.Contrib;
using Dapper;
using Microsoft.Extensions.Configuration;
using TestProject.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;
namespace TestProject.Repository
{
public class TEST_Repository
{
IConfiguration configuration;
public TEST_Repository(IConfiguration configuration)
{
this.configuration = configuration;
}
public void Insert()
{
using (var con = this.GetConnection())
{
con.Insert(new TEST { TEST_COLUMN = "test" });
}
}
public IDbConnection GetConnection()
{
return new SqlConnection(configuration.GetSection("ConnectionStrings").GetSection("DefaultConnection").Value);
}
}
}
The Insert method you are looking for lives inside of the Dapper.Contrib.Extensions namespace, as can be seen in the source, included for completeness:
namespace Dapper.Contrib.Extensions
{
...
public static long Insert<T>(this IDbConnection connection, ...)
...
}
Hence, in order to use the Extension methods, you should add the following line to your code:
using Dapper.Contrib.Extensions;

Invoke C# .NET Core Lambda from AWS CodePipeline Action

AWS CodePipeline allows you to invoke a custom Lambda from an action as described here, https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.htmltion
I am having trouble determining how my C# Lambda function should be defined in order to access the input data from the pipeline.
I tried numerous attempts, was thinking it would be something similar to below. I have also tried to create my own C# classes that the input JSON data would be deserialized to.
public void FunctionHandler( Amazon.CodePipeline.Model.Job
CodePipeline, ILambdaContext context)
I was able to find out a solution. Initially the first step that helped was to change the input parameter for my lambda function to a Stream. I was then able to convert the stream to a string and determine exactly what was being sent to me, e.g
public void FunctionHandler(Stream input, ILambdaContext context)
{
....
}
Then, based on the input data I was able to map it to a C# class that wrapped the AWS SDK Amazon.CodePipeline.Model.Job class. It had to be mapped to the json property "CodePipeline.job". The below code worked, I was able to retrieve all input values.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.CodePipeline;
using Newtonsoft.Json;
using System.IO;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
namespace lambdaEmptyFunction
{
public class Function
{
public class CodePipelineInput
{
[JsonProperty("CodePipeline.job")]
public Amazon.CodePipeline.Model.Job job { get; set; }
}
public void FunctionHandler(CodePipelineInput input, ILambdaContext context)
{
context.Logger.LogLine(string.Format("data {0} {1} {2}", input.job.AccountId, input.job.Data.InputArtifacts[0].Location.S3Location.BucketName, input.job.Id));
}
}
}

ASP.NET StreamWriter filename as variable

I have some ASP.net code that I am working with and I am running into a silent failing.
using System;
using System.IO;
using System.Web;
using System.Web.Services;
public partial class _Default : System.Web.UI.Page
{
[WebMethod(EnableSession=false)]
public static string ProcessData()
{
string chartFile = HttpContext.Current.Server.MapPath("~/Example/chartData.json");
//StreamWriter chartData = new StreamWriter(chartFile);
StreamWriter chartData = new StreamWriter("C:\\_Sites\\Example\\chartData.json");
chartData.WriteLine("Test This Out");
chartData.Flush();
chartData.Close(); // Close the instance of StreamWriter.
chartData.Dispose(); // Dispose from memory.
return chartFile;
}
}
The code I have commented out fails silently. I know the path is being correctly placed into chartFile. I think StreamWriter is not super happy about the var possibly due to the : and \ not being escaped in the string.
I cannot provide a direct path due to the nature of the deployment server. Any suggestions on how to get StreamWriter to play nice with the string contained in chartFile?
Thanks in advance.

Utilizing a WCF channel from an IIS ASP.net IHttpModule

I have an ASP.net project which involves using a custom IHttpModule. This module will sit in the pipeline and when certain criteria match up, it should invoke a method on a WCF service hosted in a simple C# console application on the same machine.
The code for the module is below:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.SessionState;
using System.Web;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Configuration;
using System.ServiceModel;
using SimpleFarmStateServer;
namespace SimpleFarm
{
public class SimpleFarmModuleSS : IHttpModule, IRequiresSessionState
{
protected string cache_directory = "";
// WCF
ChannelFactory<IStateServer> factory;
IStateServer channel;
public void Dispose() { }
public void Init(System.Web.HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
setupFactory();
}
void setupFactory()
{
factory = new ChannelFactory<IStateServer>(
new NetNamedPipeBinding(),
"net.pipe://localhost/StateServer");
}
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
try
{
if (factory.State != CommunicationState.Opened)
setupFactory();
channel = factory.CreateChannel();
channel.LogAccess("Hello World!");
}
catch (Exception ex)
{
}
finally
{
factory.Close();
}
}
}
}
My problem is that this runs the first time, but then subsequent attempts cause this error message
The communication object,
System.ServiceModel.Channels.ServiceChannel,
cannot be used for communication
because it is in the Faulted state.
It seems as if I am doing something wrong, and I am new to WCF in general so this is very likely.
I think the issue is surrounding the ChannelFactory being recreated, and this causes the faulted state.
The specific error probably means the factory faulted, threw an exception (which you're swallowing) and then when the finally block executes, the factory.Close() call fails because the factory is faulted (if a WCF object is faulted, you need to call Abort() on it, not Close()).

Resources