webRequest 호출시 (401) Unauthorized 에러가 발생한 경우 처리한다.

 

HttpWebRequest myReq = ...

myReq.UseDefaultCredentials = true;

myReq.PreAuthenticate      = true;

myReq.Credentials          = CredentialCache.DefaultCredentials;

 

 

참고

https://stackoverflow.com/questions/10205854/error-the-remote-server-returned-an-error-401-unauthorized

어느날 C 드라이브가 용량이 좀 차서

파일을 정리하는데 엄청난양의 Nuget Package 파일들이 디스크 용량을

잡아 먹고 있는걸 확인했다.

이를 수동으로 지우기 보다는 Visual Studio 에서 지우는 방법이 있다.

Visual Studio 에서 도구>옵션 의 옵션창에서

Nuget 패키지 관리자를 선택하면 '모든 NuGet 캐시 지우기' 버튼이 있는데

이를 클릭하면 삭제 할수 있다.

 

1.

https://stackoverflow.com/questions/989281/how-can-i-programmatically-limit-my-programs-cpu-usage-to-below-70

아래 내용은 Process.Start() 이후

process.PriorityClass = ProcessPriorityClass.BelowNormal;

처리를 해줘야 효과를 볼수 있다.

 

    public static class ProcessHelper

    {

        [Flags]

        public enum ThreadAccess : int

        {

            TERMINATE = (0x0001),

            SUSPEND_RESUME = (0x0002),

            GET_CONTEXT = (0x0008),

            SET_CONTEXT = (0x0010),

            SET_INFORMATION = (0x0020),

            QUERY_INFORMATION = (0x0040),

            SET_THREAD_TOKEN = (0x0080),

            IMPERSONATE = (0x0100),

            DIRECT_IMPERSONATION = (0x0200)

        }

 

        [DllImport("kernel32.dll")]

        static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);

 

        [DllImport("kernel32.dll")]

        static extern uint SuspendThread(IntPtr hThread);

 

        [DllImport("kernel32.dll")]

        static extern int ResumeThread(IntPtr hThread);

 

        [DllImport("kernel32.dll")]

        static extern int CloseHandle(IntPtr hThread);

 

        public static void ThrottleProcess(int processId, double limit)

        {

            var process = Process.GetProcessById(processId);

            var processName = process.ProcessName;

            var p = new PerformanceCounter("Process", "% Processor Time", processName);

            while (true)

            {

                var interval = 100;

                Thread.Sleep(interval);

 

                var currentUsage = p.NextValue() / Environment.ProcessorCount;

                if (currentUsage < limit) continue;

                var suspensionTime = (currentUsage-limit) / currentUsage * interval;

                SuspendProcess(processId);

                Thread.Sleep((int)suspensionTime);

                ResumeProcess(processId);

            }

        }

 

        private static void SuspendProcess(int pid)

        {

            var process = Process.GetProcessById(pid);

 

            if (process.ProcessName == string.Empty)

                return;

 

            foreach (ProcessThread pT in process.Threads)

            {

                IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);

 

                if (pOpenThread == IntPtr.Zero)

                {

                    continue;

                }

 

                SuspendThread(pOpenThread);

 

                CloseHandle(pOpenThread);

            }

        }

 

        private static void ResumeProcess(int pid)

        {

            var process = Process.GetProcessById(pid);

 

            if (process.ProcessName == string.Empty)

                return;

 

            foreach (ProcessThread pT in process.Threads)

            {

                IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);

 

                if (pOpenThread == IntPtr.Zero)

                {

                    continue;

                }

 

                var suspendCount = 0;

 

                do

                {

                    suspendCount = ResumeThread(pOpenThread);

                } while (suspendCount > 0);

 

                CloseHandle(pOpenThread);

            }

        }

    }

 

2.

https://stackoverflow.com/questions/989281/how-can-i-programmatically-limit-my-programs-cpu-usage-to-below-70

 

아래 내용은 process.PriorityClass = ProcessPriorityClass.BelowNormal 처리를 하지 않아도 효과를 볼수 있다.

이 내용이 확실하게 제어를 해주는것 같다

 

    public class ProcessManager

    {

        [DllImport("kernel32.dll", EntryPoint = "CreateJobObjectW", CharSet = CharSet.Unicode)]

        public static extern IntPtr CreateJobObject(SecurityAttributes JobAttributes, string lpName);

 

        [DllImport("kernel32.dll")]

        [return: MarshalAs(UnmanagedType.Bool)]

        static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);

 

        [DllImport("kernel32.dll")]

        static extern bool SetInformationJobObject(IntPtr hJob, JOBOBJECTINFOCLASS JobObjectInfoClass, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);

 

        public class SecurityAttributes

        {

            public int nLength;

            public IntPtr pSecurityDescriptor;

            public bool bInheritHandle;

 

            public SecurityAttributes()

            {

                this.bInheritHandle = true;

                this.nLength = 0;

                this.pSecurityDescriptor = IntPtr.Zero;

            }

        }

 

        public enum JOBOBJECTINFOCLASS

        {

            JobObjectAssociateCompletionPortInformation = 7,

            JobObjectBasicLimitInformation = 2,

            JobObjectBasicUIRestrictions = 4,

            JobObjectEndOfJobTimeInformation = 6,

            JobObjectExtendedLimitInformation = 9,

            JobObjectSecurityLimitInformation = 5,

            JobObjectCpuRateControlInformation = 15

        }

 

        [StructLayout(LayoutKind.Explicit)]

        //[CLSCompliant(false)]

        struct JOBOBJECT_CPU_RATE_CONTROL_INFORMATION

        {

            [FieldOffset(0)]

            public UInt32 ControlFlags;

            [FieldOffset(4)]

            public UInt32 CpuRate;

            [FieldOffset(4)]

            public UInt32 Weight;

        }

 

        public enum CpuFlags

        {

            JOB_OBJECT_CPU_RATE_CONTROL_ENABLE = 0x00000001,

            JOB_OBJECT_CPU_RATE_CONTROL_WEIGHT_BASED = 0x00000002,

            JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP = 0x00000004

        }

 

        public static void ThrottleProcess(Process process)

        {

            //Limit the CPU usage to 45%

            var jobHandle = CreateJobObject(null, null);

            AssignProcessToJobObject(jobHandle, process.Handle);

            var cpuLimits = new JOBOBJECT_CPU_RATE_CONTROL_INFORMATION();

            cpuLimits.ControlFlags = (UInt32)(CpuFlags.JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | CpuFlags.JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP);

            cpuLimits.CpuRate = 45 * 100; // Limit CPu usage to 45%

            var pointerToJobCpuLimits = Marshal.AllocHGlobal(Marshal.SizeOf(cpuLimits));

            Marshal.StructureToPtr(cpuLimits, pointerToJobCpuLimits, false);

            if (!SetInformationJobObject(jobHandle, JOBOBJECTINFOCLASS.JobObjectCpuRateControlInformation, pointerToJobCpuLimits, (uint)Marshal.SizeOf(cpuLimits)))

            {

                Console.WriteLine("Error !");

            }

        }

    }

 

 

사용예시

 

Process process = new Process();

process.EnableRaisingEvents   = false;

process.StartInfo.FileName    = "Test.exe";

//process.StartInfo.Verb        = "Open";

process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

//process.StartInfo.Arguments   = argument;

 

process.Start();

 

// 1번 방법

process.PriorityClass = ProcessPriorityClass.BelowNormal;

ProcessHelper.ThrottleProcess(process.Id, 0.5);

 

// 2번 방법

ProcessManager.ThrottleProcess(process);

 

        #region ImageToBytes

        /// <summary>

        /// 이미지를 바이트 배열로 변환합니다.

        /// </summary>

        /// <param name="image">변환할 이미지입니다.</param>

        /// <returns>바이트배열입니다.</returns>

        byte[] ImageToBytes(Image image)

        {

            // 이미지 포멧을 가져옵니다.

            ImageFormat imageFormat = image.RawFormat;

            using (MemoryStream memoryStream = new MemoryStream())

            {

                // 이미지 포멧에 따라 스트림에 이미지를 저장합니다.

                if (imageFormat.Equals(ImageFormat.Jpeg))

                {

                    image.Save(memoryStream, ImageFormat.Jpeg);

                }

                else if (imageFormat.Equals(ImageFormat.Png))

                {

                    image.Save(memoryStream, ImageFormat.Png);

                }

                else if (imageFormat.Equals(ImageFormat.Bmp))

                {

                    image.Save(memoryStream, ImageFormat.Bmp);

                }

                else if (imageFormat.Equals(ImageFormat.Gif))

                {

                    image.Save(memoryStream, ImageFormat.Gif);

                }

                else if (imageFormat.Equals(ImageFormat.Icon))

                {

                    image.Save(memoryStream, ImageFormat.Icon);

                }

 

                // 배열을 선언합니다.

                byte[] buffer = new byte[memoryStream.Length];

 

                // 배열을 체웁니다.

                memoryStream.Seek(0, SeekOrigin.Begin);

                memoryStream.Read(buffer, 0, buffer.Length);

 

                return buffer;

            }

        }

        #endregion

 

* 빗썸 코인정보 Class

    public class CoinInfo

    {

        public string CoinType       { get; set; }

        public DateTime CoinTime     { get; set; }

        public string Status         { get; set; }

        public int OpeningPrice     { get; set; }

        public int ClosingPrice     { get; set; }

        public int MinPrice         { get; set; }

        public int MaxPrice         { get; set; }

        public string AveragePrice { get; set; }

        public string UnitsTraded   { get; set; }

        public string Volume1Day    { get; set; }

        public string Volume7Day    { get; set; }

        public int BuyPrice         { get; set; }

        public int SellPrice        { get; set; }

        public string Date           { get; set; }

    }

 

* 빗썸 데이터 가져오기

 

                //string page = "https://api.bithumb.com/public/ticker/BTC"; // 특정 화폐정보만 가져올때

                string page = "https://api.bithumb.com/public/ticker/ALL";

                HttpClient client = new HttpClient();

                var response = await client.GetAsync(page);

                if (!response.IsSuccessStatusCode) return;

 

                using (HttpContent content = response.Content)

                {

                    string result = await content.ReadAsStringAsync();

                    var o = JsonConvert.DeserializeObject(result);

                    JObject JObj = JObject.Parse(result);

 

                    //BTC,ETH,DASH,LTC,ETC,XRP,BCH,XMR,ZEC,QTUM,BTG,EOS

                    string[] coinTypes = "BTC,ETH,DASH,LTC,ETC,XRP,BCH,XMR,ZEC,QTUM,BTG,EOS".Split(',');

 

                    string status = JObj["status"].ToString();

                    if (status != "0000") return;

 

                    string date = JObj["data"]["date"].ToString();

 

                    // 데이터 가져온 시간입니다.

                    DateTime coinTime = DateTime.Now;

                    List<CoinInfo> coinInfoList = new List<CoinInfo>();

 

                    foreach (string coinType in coinTypes)

                    {

                        CoinInfo coinInfo = new CoinInfo() { CoinType = coinType, Status = status, Date = date, CoinTime = coinTime };

 

                        coinInfo.OpeningPrice = int.Parse(JObj["data"][coinType]["opening_price"].ToString());

                        coinInfo.ClosingPrice = int.Parse(JObj["data"][coinType]["closing_price"].ToString());

                        coinInfo.MinPrice = int.Parse(JObj["data"][coinType]["min_price"].ToString());

                        coinInfo.MaxPrice = int.Parse(JObj["data"][coinType]["max_price"].ToString());

                        coinInfo.AveragePrice = JObj["data"][coinType]["average_price"].ToString();

                        coinInfo.UnitsTraded = JObj["data"][coinType]["units_traded"].ToString();

                        coinInfo.Volume1Day = JObj["data"][coinType]["volume_1day"].ToString();

                        coinInfo.Volume7Day = JObj["data"][coinType]["volume_7day"].ToString();

                        coinInfo.BuyPrice = int.Parse(JObj["data"][coinType]["buy_price"].ToString());

                        coinInfo.SellPrice = int.Parse(JObj["data"][coinType]["sell_price"].ToString());

 

                        coinInfoList.Add(coinInfo);

                    }

                }

 

* 빗썸 예시 데이터 (Json) - 2019-05-21 오후10:45 데이터

사용자 컨트롤 작성시 사용자 컨트롤에 다른 컨트롤들을

배치 시킬수 있도록 하기 위한 방법입니다.

 

UserControl (TestControl) 을 만들고 사용자가 편집 가능하게 할 컨트롤을 아래 처럼 정의합니다.

 

namespace Test

{

    public partial class TestControl : UserControl

    {

        /// <summary>

        /// 사용자 정의 판넬입니다.

        /// </summary>

        [Category("Test")]

        [Browsable(false)]

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

        public Panel UserPanel => this.userPanel;

    }

}

 

ParentControlDesigner 를 상속받는 디자이너 클래스를 추가합니다.

 

using System.ComponentModel;

using System.Windows.Forms.Design;

 

namespace Test

{

   public class TestControlDesigner : ParentControlDesigner

    {

        public override void Initialize(IComponent component)

        {

            base.Initialize(component);

 

            TestControl testControl = component as TestControl;

            if (dsGridSelector != null)

            {

                base.EnableDesignMode(dsGridSelector.UserPanel, "UserPanel");

            }

        }

    }

}

 

UserControl 의 상단에 아래 처럼 처리합니다.

 

namespace Test

{

    [Designer(typeof(TestControlDesigner))]

    public partial class TestControl : UserControl

    {

        /// <summary>

        /// 사용자 정의 판넬입니다.

        /// </summary>

        [Category("Test")]

        [Browsable(false)]

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

        public Panel UserPanel => this.userPanel;

    }

}

 

이게 디자이너 단에서 UserPanel 부분으로 다른 컨트롤 들을 배치 시킬수 있습니다.

 

만약 Panel 안의 Panel 을 처리하고 싶을때는 부모 판넬도 위와 같은 처리를 해야

정상적으로 동작합니다.

 

예시)

Panel1 안에 Panel2 가 있는 경우 Panel2 로 디자이너에서 편집이 가능하게 할 경우

 

namespace Test

{

    [Designer(typeof(TestControlDesigner))]

    public partial class TestControl : UserControl

    {

        /// <summary>

        /// 사용자 정의 판넬1입니다.

        /// </summary>

        [Category("Test")]

        [Browsable(false)]

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

        public Panel UserPanel1 => this.userPanel1;

 

        /// <summary>

        /// 사용자 정의 판넬2입니다.

        /// </summary>

        [Category("Test")]

        [Browsable(false)]

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

        public Panel UserPanel2 => this.userPanel2;

 

    }

}

 

 

using System.ComponentModel;

using System.Windows.Forms.Design;

namespace Test

{

    public class TestControlDesigner : ParentControlDesigner

    {

        public override void Initialize(IComponent component)

        {

            base.Initialize(component);

 

            TestControl testControl = component as TestControl;

            if (dsGridSelector != null)

            {

                base.EnableDesignMode(dsGridSelector.UserPanel1, "UserPanel1");

                base.EnableDesignMode(dsGridSelector.UserPanel2, "UserPanel2");

            }

        }

    }

}

 

 

 

 

 

 

Task.WaitAll(t1,t2);
Parallel.Invoke(()=>{work(1,2)}
목(mock) : 대리인 역할을 하는 객체
Linq 의 sort 는 원래 데이터를 제거 하고 orderby 는 원래 데이터를 유지한다.
Cast 는 예외를 발생 시킨다.- 단순히 형을 반환한다.
OfType 는 예외를 발생 시키지 않는다. - 형변환은 물론 형에 일치하는 데이터를 추출한다.

https://csharp.hotexamples.com/examples/System.Drawing/Image/Save/php-image-save-method-examples.html

결론.

const 컴파일 상수는 성능이 매우 중요하고 상수의 값이 절대로 바뀌지 않는 경우만 제한적으로 사용하는 것이 좋다.

 

readonly 런타임 상수는..

- const 에 비해 느리지만 유연성이 좋다.

- 어떤 타입과도 함께 사용할수 있다.

- 메서드내에서는 선언할 수 없다.

- 클래스별로 서로 다른 값을 가질 수 있다.

- 값을 변경 한 경우 리빌드 하지 않아도 런타임시 값을 참조하기 때문에 어샘블리만 리빌드 되어있으면 변경된 값을 가져올수 있다.

* 런타임에 값이 평가되어 값을 가지지 않고 상수에 대한 참조 컴파일 된다.

* 맴버 초기화 구문뿐 아니라 생성자를 통해서도 초기화 가능하다.

 

const 컴파일 타임 상수는..

- 속도가 빠르고 변경이 불가능하다.

- 내장자료형(primitive types)과 enums,string으로만 사용할 수 있다.

- const. 컴파일 타임 상수는 메서드내에서 정의될 수 있다.

- 하나의 값만 가질 수 있다.

- 값을 변경 한 경우 리빌드 해야함 참조한 프로젝트에서 변경된 값을 가져올수 있다.

 

1. 지역변수를 선언할 때는 var 를 사용하는 것이 낫다.

정확한 반환 타입을 알면 상관없지만 어설프게 정확한 반환타입을 알지 못한채 명시적 타입을 쓰게되면

득보다 실이 많다.

변수의 타입보다는 변수의 의미파악에 더 집중할 수 있게 한다.

가독성과 자동타입변환 과정으로 인해 버그를 만들수도 있지만

var 변수로 인해 가독성이 방해되는 코드라면 대부분

명시적으로 써도 가독성은 불편한건 마찬가지이다.

+ Recent posts